1. 前言
在 Spring Boot中,使用@Scheduled
注解来定义定时任务时,定时任务不执行;或未在规定时间执行。
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class MySchedule {
/**
* 5秒执行一次
*/
@Scheduled(cron = "0/5 * * * * ?")
public void task1() {
System.out.println("Scheduled task-1111 is running ... ...");
}
/**
* 10秒执行一次
*/
@Scheduled(cron = "0/10 * * * * ?")
public void task2() {
System.out.println("Scheduled task-2222 is running ... ...");
}
}
2. 解决
2.1 定时任务不执行
- 在启动类或者相关Configuration类上,添加
@EnableScheduling
注解; - 然后在定义定时任务的类上,添加 @Component 注解
2.2 未按规定时间执行
如果使用@Scheduled注解定义了多个定时任务,但是任务未按规定时间执行。
-
增加配置类,改变线程池大小
import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.SchedulingConfigurer; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.scheduling.config.ScheduledTaskRegistrar; /** * @Description : scheduler配置类 */ @Configuration public class ScheduledTaskConfig implements SchedulingConfigurer { @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); taskScheduler.setPoolSize(20); // 线程池大小设置为20 taskScheduler.initialize(); taskRegistrar.setTaskScheduler(taskScheduler); } }
原因分析:
-
查看 @Scheduled注解的源码:每一个有@Scheduled注解的方法都会被注册为一个ScheduledAnnotationBeanPostProcessor
-
继续跟踪,看ScheduledAnnotationBeanPostProcessor的源码
从图中的这句话得知,如果我们不主动配置我们需要的TaskScheduler,Spring Boot会默认使用一个单线程的scheduler来处理我们用@Scheduled注解实现的定时任务
要的TaskScheduler,Spring Boot会默认使用一个单线程的scheduler来处理我们用@Scheduled注解实现的定时任务
因为默认是单线程处理,因此就会导致有的有的任务在规定时间内没执行,需要等待。