spring boot 整合 scheduled 实现定时任务
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
启用定时任务的注解
定时任务的启动需要添加注解 @EnableScheduling 来启用,如果不添加这个注解则无法启动,添加的位置不固定
@SpringBootApplication
@EnableScheduling
public class ScheduledApplication {
public static void main(String[] args) {
SpringApplication.run(ScheduledApplication.class, args);
}
}
定义定时任务
在项目中如果启用的定时任务的配置后,需要在要启动的定时任务的方法上添加注解 @Scheduled 标识定时任务,该注解可以使用在注解和方法上,不能使用在类上。
@Scheduled注解定义了三种策略是实现延时任务的方式。部分源码如下:
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {
/**
* 通过cron 表达式进行定时任务设置,比较灵活
*/
String cron() default "";
/**
* 按照固定延迟周期执行,指的是两次任务执行之间的间隔,在上一次任务执行结束开始计算固定延时时间,后才开始执行任务,如果上一次任务阻塞,会造成下一次任务也执行时间较晚
*/
long fixedDelay() default -1;
/**
* 按照固定频率执行,指的是两次任务开始时间的间隔,在上一次任务执行开始后进行计时,到达执行时间后开始执行下一次任务,但是在上一次任务执行可能还没完成
*/
long fixedRate() default -1;
/**
* 在项目启动后多久时间后才开始执行定时任务
*/
long initialDelay() default -1;
/**
* 时间单位,默认为秒
* @return
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
}
通过@Scheduled注解可知,定时任务时间设置可以通过三种策略设置:fixedRate,fixedDelay,cron
三种方式,其中cron方式设置定时任务比较灵活。
- fixedRate 适用于需要严格维持任务执行速率、即使前一个任务未结束也应启动下一个任务的场景,但可能引发并发问题。
- fixedDelay 适用于不希望任务之间相互干扰、需要等待前一个任务完全结束再开始下一个任务的场景,避免了并发问题。
- cron 适用于需要按照复杂、非固定间隔执行任务的场景,提供高度的定时策略定制能力
public class ScheduledTask {
/**
* 定时任务执行
*/
@Scheduled(cron = "* 0/10 * * * ? ")
public void fiveSecondPrint() {
try {
log.info("cron每十分钟执行一次任务:{}-{}", LocalTime.now(), new Random().nextInt(10));
} catch (Exception e) {
// 如果定时任务执行出错进行处理
}
}
/**
* 固定频率执行定时任务(执行多次),会以上次任务为执行开始时间之间保持恒定的间隔。
*/
@Scheduled(initialDelay = 1, fixedRate = 1, timeUnit = TimeUnit.HOURS)
public void fixedRate() {
try {
log.info("fixedRate每一小时执行一次任务:{}-{}", LocalTime.now(), new Random().nextInt(100));
} catch (Exception e) {
// 如果定时任务执行出错进行处理
}
}
/**
* 以上一次任务完成开始计算固定间隔后开始执行任务,如果上一次任务完成耗时较长,下一个任务会相应的延迟,始终确保两次任务之间有指定的间隔。
*/
@Scheduled(initialDelay = 1, fixedDelay = 5, timeUnit = TimeUnit.MINUTES)
public void fixedDelay() {
try {
log.info("fixedDelay执行一次任务:{}-{}", LocalTime.now(), new Random().nextInt(100));
} catch (Exception e) {
// 如果定时任务执行出错进行处理
}
}
}
定时任务相关配置
定时任务执行使用的异步的方式进行,默认的线程池大小为1,但是可以根据实际情况进行配置实现,扩展线程池容量,线程池名称以及其他配置,实现方式有两种方式分别为:
- 配置文件实现配置
- 配置类实现配置
配置文件实现日志相关配置
# 定时任务线程池设置
spring:
task:
scheduling:
# 定时任务线程池的默认大小配置
pool:
size: 5
# 定时任务线程池中线程名称的前缀
thread-name-prefix: custom-scheduling-
# 关闭策略
shutdown:
await-termination: true
配置类实现定时任务线程池配置
public class CustomerScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(scheduledExecutor());
}
/**
* 自定义线程池
*
* @return
*/
@Bean
public ThreadPoolTaskScheduler scheduledExecutor() {
ThreadPoolTaskScheduler taskExecutor = new ThreadPoolTaskScheduler();
// 核心线程数
taskExecutor.setPoolSize(2);
// 线程池的名称前缀
taskExecutor.setThreadNamePrefix("custom-schedule-");
// 设置拒绝策略
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
// 设置线程池关闭策略,等待线程池中的所有任务执行完毕
taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
taskExecutor.initialize();
return taskExecutor;
}
}
通过以上两种方式都可以实现对定时任务线程池进行自定义配置,比较推荐使用配置类的方式进行自定义定时任务的配置,可以进行自定义的配置项有很多,更加方便扩展更多的配置项,而配置类可以进行自定义配置的选项较少。