springboot项目中定时任务注解@Scheduled未按cron表达式执行
- 背景
- 问题复现
- 原因分析
- 解决方法
- 其他原因
背景
在将一个类注入到ioc后,其中定义了几个定时任务,分别是每隔十秒执行一次,但实际情况却是半小时才执行一次,故开始分析原因:spring scheduled默认为单线程,导致任务阻塞,很多时候不能按时执行原因
问题复现
这是正常情况下,各定时任务正常调度
为其中一个任务加上睡眠3分钟,发现所有的任务在睡眠期间均不会被执行
等待3分钟之后,其他任务均会被执行一次,再次进入等待;也就是说 其中一个任务未执行完毕,其他任务均不会被执行了
原因分析
将执行任务的线程打印,发现执行任务的线程均为scheduling-1
而当其中一个任务耗时或睡眠后,其他任务也使用这个线程,只能等待
解决方法
方法1- 让此方法异步处理,可以新开线程池异步 - Spring Boot 2.0 以前的实现方式
定义一个新的线程池,为耗时的线程使用,线程参数看项目调整
不推荐直接使用@Async让耗时方法异步,因其不可控
看看现在的效果,发现即便是任务2耗时,但不影响其他三个任务,而任务2本身的线程池可自行调整核心线程数与拒绝策略
方法2- 只需要修改配置(Spring Boot 2.1以后版本)
spring:task:scheduling:pool:# 最大线程数,默认是 1size: 10# 线程名称前缀,默认是 scheduling-thread-name-prefix: demoScheduling-
其他原因
添加注解@Scheduled后,未重启项目
未在启动类或@Configuration类上加@EnableScheduling
任务类上有@ConditionalOnProperty通过配置来开关