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 {@Overridepublic void configureTasks(ScheduledTaskRegistrar taskRegistrar) {ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();taskScheduler.setPoolSize(20); // 线程池大小设置为20taskScheduler.initialize();taskRegistrar.setTaskScheduler(taskScheduler);} }
原因分析:
-
查看 @Scheduled注解的源码:每一个有@Scheduled注解的方法都会被注册为一个ScheduledAnnotationBeanPostProcessor
-
继续跟踪,看ScheduledAnnotationBeanPostProcessor的源码
从图中的这句话得知,如果我们不主动配置我们需要的TaskScheduler,Spring Boot会默认使用一个单线程的scheduler来处理我们用@Scheduled注解实现的定时任务
要的TaskScheduler,Spring Boot会默认使用一个单线程的scheduler来处理我们用@Scheduled注解实现的定时任务
因为默认是单线程处理,因此就会导致有的有的任务在规定时间内没执行,需要等待。