本文由 简悦 SimpRead 转码, 原文地址 blog.csdn.net
一. 在 Spring boot 项目中实现简单的定时任务:
在 Spring boot 项目中实现定时任务通常用 Spring 的 @Scheduled 注解来完成。
示例:
1. 首先,在 Spring boot 项目中创建一个定时任务类,例如:TaskScheduler:
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class TaskScheduler {
// 每隔5秒执行一次任务
@Scheduled(fixedRate = 5000)
public void scheduledTask() {
System.out.println("定时任务执行啦!");
}
}
2. 在启动类或者配置类上添加 @EnableScheduling 注解,以开启定时任务的支持:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
3. 完成以上步骤后,当运行 Spring Boot 时,定时任务会按照 @Scheduled 注解中配置的时间间隔执行。
二. @Scheduled 注解:
@Scheduled 注解是 Spring 框架中用于配置定时任务的注解之一。通过在方法上添加 @Scheduled 注解,可以指定方法在特定时间执行,或者以固定时间间隔执行。在使用 @Scheduled 时,可以指定多种参数,包括 fixedDelay(固定延迟时间执行),fixedRate(固定频率执行),cron 表达式(按照 cron 表达式规则执行)等,以满足不同的定时任务需求。
@Scheduled 各个参数用法:
fixedDelay:
- 用法:
@Scheduled(fixedDelay = 1000)- 解释:指定方法执行结束后延迟多久再次执行,单位为毫秒。
- 示例:
@Scheduled(fixedDelay = 5000)表示每次任务执行结束后延迟 5 秒再次执行。fixedRate:
- 用法:
@Scheduled(fixedRate = 2000)- 解释:指定方法开始执行后多久再次执行,单位为毫秒。不关心方法执行时间长短,固定频率执行。
- 示例:
@Scheduled(fixedRate = 3000)表示每隔 3 秒执行一次任务,不论任务执行时间长短。initialDelay:
- 用法:
@Scheduled(initialDelay = 5000, fixedRate = 2000)- 解释:指定首次执行任务的延迟时间,单位为毫秒。
- 示例:
@Scheduled(initialDelay = 10000, fixedRate = 3000)表示首次执行任务将在 10 秒后,之后每隔 3 秒执行一次。cron:
- 用法:
@Scheduled(cron = "0 0 12 * * ?")- 解释:使用 cron 表达式来指定任务执行的时间规则。
- 示例:
@Scheduled(cron = "0 0/5 8-20 * * ?")表示在每天的上午 8 点到晚上 8 点,每隔 5 分钟执行一次任务。
cron 表达式的各个字段及其含义:
- 秒(Seconds):取值范围为 0-59。
- 分钟(Minutes):取值范围为 0-59。
- 小时(Hours):取值范围为 0-23。
- 日期(Day of month):取值范围为 1-31。
- 月份(Month):取值范围为 1-12 或使用英文缩写(如 JAN-DEC)。
- 星期(Day of week):取值范围为 0-7 或使用英文缩写(SUN-SAT),其中 0 和 7 都表示星期日。
cron表达式的格式如下:import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @Service public class MyService { @Async public void doSomethingAsync() { // 异步执行的任务代码 } }例如,如果要每天中午 12 点执行一次任务,可以使用如下的
cron表达式:import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; @Configuration @EnableAsync public class AppConfig { // 配置信息 }在上述表达式中,
0 0 12 * * ?表示每天中午 12 点执行一次任务。在实际使用中,根据具体的需求可以灵活设置cron表达式来指定定时任务的执行时间。需要注意的是,cron表达式中不同字段之间用空格分隔,同时还可以使用通配符、区间等方式来设置更复杂的定时规则。
在cron表达式中,可以使用一些特殊的符号来设置更复杂的定时规则。以下是常用的通配符和区间符号:
通配符:
*:表示匹配任意值。例如,*在分钟字段表示每分钟都执行。?:仅用于日和星期字段,表示不指定具体值。区间:
-:表示范围。例如,1-5在小时字段表示 1 点到 5 点之间每个整点触发。/:表示步长。例如,0/5在秒字段表示每隔 5 秒执行一次。列表:
,:表示列表。可以指定多个值逗号分隔。例如,1,3,5在小时字段表示 1 点、3 点和 5 点各执行一次。通配符和区间的结合:
- 可以结合通配符和区间来设置更复杂的定时规则。例如,
0 0 0 1-10 * ?表示在每个月的 1 号到 10 号的午夜零点触发。工作日和非工作日:
W:表示最接近给定日期的工作日(周一至周五)。例如,15W在日字段表示离每月 15 号最近的工作日触发。L:表示最后一天。例如,L在日字段表示每个月的最后一天触发。
三. 实现定时任务的异步执行:
为什么要实现异步执行定时任务?主要有以下优点:
提高系统性能:
- 异步执行可以避免因为同步执行而造成的阻塞,提高系统的并发能力和响应速度。通过异步执行,系统可以同时处理多个任务,充分利用系统资源,提升系统整体性能。
增强用户体验:
- 异步执行可以确保用户操作的及时响应,避免因为任务耗时长而导致用户界面假死或响应缓慢的情况发生。用户在等待任务完成的过程中可以继续进行其他操作,提升用户体验。
任务解耦和模块化:
- 通过异步执行,可以将任务之间的耦合度降低,实现任务的解耦和模块化。不同的任务可以独立执行,各自管理自己的状态和资源,提高系统的灵活性和可维护性。
提高系统稳定性:
- 异步执行可以将任务的执行隔离开来,降低任务之间的相互影响,提高系统的稳定性和容错能力。即使某个任务执行失败,也不会对系统的整体运行造成严重影响。
资源管理和调度优化:
- 通过异步执行,可以更好地管理系统资源,优化任务调度策略,提高系统的资源利用率和效率。合理安排任务的执行顺序和时间,可以更好地满足业务需求。
实现定时任务异步执行的方法有多种,这里主要介绍使用 Spring Framework 中的 @Async 注解来实现异步执行定时任务,通过在方法上添加 @Async 注解,Spring 会在调用该方法时自动创建一个新的线程来执行该方法,从而实现异步执行。
代码示例:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@Configuration
public class AppConfig implements AsyncConfigurer {
@Override
@Bean
public TaskExecutor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.initialize();
return executor;
}
}
在使用 @Async 注解时,需要在 Spring 配置类或者启动类上添加 @EnableAsync 注解来启用对异步方法的支持,例如:
import org.springframework.scheduling.annotation.Async;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Async("getAsyncExecutor")
public void doSomethingAsync() {
// 异步执行的任务代码
}
}
当使用@Async注解时,Spring 会默认使用一个线程池来执行异步方法。这个线程池是由 Spring 自动配置的,默认情况下,它会使用一个SimpleAsyncTaskExecutor来执行异步方法。
我们可以在 Spring 的配置类中创建一个TaskExecutor bean,并在使用@Async注解时指定要使用的线程池。下面是一个简单的示例:
@Async("threadPoolTaskExecutor")
@Scheduled(cron = "0 0/30 * * * ?")
public void GrabFileInformation() {
dataService.getAllDataTASK();
log.info("执行了抓取数据定时任务!");
}
在上面的示例中,我们创建了一个ThreadPoolTaskExecutor bean,并通过重写AsyncConfigurer接口的getAsyncExecutor()方法,返回我们自定义的线程池实例。在这个示例中,我们设置了线程池的核心线程数、最大线程数和队列容量,并将其初始化后返回给 Spring 容器。
接着,我们可以在需要使用异步方法的地方,使用@Async注解并指定要使用的线程池。例如:
import org.springframework.scheduling.annotation.Async;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Async("getAsyncExecutor")
public void doSomethingAsync() {
// 异步执行的任务代码
}
}
在上面的示例中,我们在doSomethingAsync方法上使用了@Async("getAsyncExecutor")注解,指定了要使用的线程池名为getAsyncExecutor,这样就可以使用我们自定义的线程池来执行异步方法了。
那么要实现定时任务的异步执行就很简单了,例如:
@Async("threadPoolTaskExecutor")
@Scheduled(cron = "0 0/30 * * * ?")
public void GrabFileInformation() {
dataService.getAllDataTASK();
log.info("执行了抓取数据定时任务!");
}
记得在配置类上加上 @EnableAsync 和 @EnableScheduing 注解即可。