Springboot中使用@Scheduled开启的定时任务,默认使用的是单线程的线程池
public class ContextLifecycleScheduledTaskRegistrar extends ScheduledTaskRegistrar implements SmartInitializingSingleton {
@Override
public void afterPropertiesSet() {
// no-op
}
@Override
public void afterSingletonsInstantiated() {
scheduleTasks();
}
}
这就会导致多个任务时,可能不会按预期的时间执行
举个例子,这里我开启了两个定时任务
task1每3s执行一次,task2每1s执行一次
@Component
@Slf4j
public class Task {
@Scheduled(fixedRate = 3000)
public void task1() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
log.info("task1:{}", LocalDateTime.now());
}
@Scheduled(fixedRate = 1000)
public void task2() {
log.info("task2:{}", LocalDateTime.now());
}
}
打印日志如下
可以看到task1执行阻塞3s后,task2才开始执行,并且一次性执行了3次
这显然是不符合预期的
2024-08-13 11:35:09.330 INFO 32804 --- [ scheduling-1] com.yimin.demo.config.Task : task1:2024-08-13T11:35:09.330
2024-08-13 11:35:09.330 INFO 32804 --- [ scheduling-1] com.yimin.demo.config.Task : task2:2024-08-13T11:35:09.330
2024-08-13 11:35:09.330 INFO 32804 --- [ scheduling-1] com.yimin.demo.config.Task : task2:2024-08-13T11:35:09.330
2024-08-13 11:35:09.330 INFO 32804 --- [ scheduling-1] com.yimin.demo.config.Task : task2:2024-08-13T11:35:09.330
2024-08-13 11:35:12.339 INFO 32804 --- [ scheduling-1] com.yimin.demo.config.Task : task1:2024-08-13T11:35:12.339
2024-08-13 11:35:12.339 INFO 32804 --- [ scheduling-1] com.yimin.demo.config.Task : task2:2024-08-13T11:35:12.339
2024-08-13 11:35:12.339 INFO 32804 --- [ scheduling-1] com.yimin.demo.config.Task : task2:2024-08-13T11:35:12.339
2024-08-13 11:35:12.339 INFO 32804 --- [ scheduling-1] com.yimin.demo.config.Task : task2:2024-08-13T11:35:12.339
问题就在于线程池中只有一个线程
要解决这个问题,我们只需要自定义线程池中的线程数即可
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(2);
threadPoolTaskScheduler.initialize(); // optional
taskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
}
}
配置完再运行
task1每3s执行一次,task2每1s执行一次
两个任务使用的是不同线程,彼此互不干扰,结果符合预期
2024-08-13 11:45:21.693 INFO 20524 --- [TaskScheduler-1] com.yimin.demo.config.Task : task2:2024-08-13T11:45:21.693
2024-08-13 11:45:22.694 INFO 20524 --- [TaskScheduler-1] com.yimin.demo.config.Task : task2:2024-08-13T11:45:22.694
2024-08-13 11:45:23.679 INFO 20524 --- [TaskScheduler-1] com.yimin.demo.config.Task : task2:2024-08-13T11:45:23.679
2024-08-13 11:45:23.679 INFO 20524 --- [TaskScheduler-2] com.yimin.demo.config.Task : task1:2024-08-13T11:45:23.679
2024-08-13 11:45:24.679 INFO 20524 --- [TaskScheduler-1] com.yimin.demo.config.Task : task2:2024-08-13T11:45:24.679
2024-08-13 11:45:25.693 INFO 20524 --- [TaskScheduler-1] com.yimin.demo.config.Task : task2:2024-08-13T11:45:25.693
2024-08-13 11:45:26.689 INFO 20524 --- [TaskScheduler-1] com.yimin.demo.config.Task : task2:2024-08-13T11:45:26.689
2024-08-13 11:45:26.689 INFO 20524 --- [TaskScheduler-2] com.yimin.demo.config.Task : task1:2024-08-13T11:45:26.689