Spring Boot @Scheduled配置两个cron定时任务无法按预期全部执行问题排查
问题根因
你遇到的问题是Spring Framework版本的已知bug导致的:
- 你使用的Spring Boot 2.2.4.RELEASE内置的Spring Framework版本为5.2.3.RELEASE,该版本存在Cron调度计算逻辑的缺陷,当多个Cron任务的执行间隔超过1小时时,首个任务执行完成后,后续任务的下一次执行时间会计算错误,最终导致任务无法触发。
- 你测试时两个任务间隔1分钟可以正常执行,间隔1小时以上仅首个任务执行,完全符合该bug的表现。
- 另外可以排除默认单线程调度池阻塞的问题:你的任务逻辑仅为打印日志,执行耗时极短,不会出现线程阻塞的情况。
解决方案
方案1(推荐):升级Spring Boot版本
直接将Spring Boot版本升级到2.2.5.RELEASE及以上即可,该版本对应的Spring Framework 5.2.4.RELEASE已经官方修复了上述Cron调度bug。
方案2:单独升级spring-context依赖
如果暂时无法升级Spring Boot整体版本,可以单独指定spring-context依赖版本为5.2.4.RELEASE及以上。
Gradle配置参考:
implementation("org.springframework:spring-context:5.2.4.RELEASE")
Maven配置参考:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.4.RELEASE</version> </dependency>
可选优化:配置多线程调度池
Spring @Scheduled默认使用单线程调度池,若后续有执行耗时较长的任务,容易阻塞其他任务执行,可以新增调度配置类自定义线程池:
import org.springframework.context.annotation.Configuration import org.springframework.scheduling.annotation.SchedulingConfigurer import org.springframework.scheduling.config.ScheduledTaskRegistrar import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler @Configuration class SchedulerConfig : SchedulingConfigurer { override fun configureTasks(taskRegistrar: ScheduledTaskRegistrar) { val taskScheduler = ThreadPoolTaskScheduler() // 线程池大小根据实际任务数量调整 taskScheduler.poolSize = 5 taskScheduler.setThreadNamePrefix("scheduled-task-") taskScheduler.initialize() taskRegistrar.setTaskScheduler(taskScheduler) } }
内容的提问来源于stack exchange,提问作者Yoshihito Koyama
相关产品推荐
相关产品推荐

