应用中我们通常采用定时任务不断监听配置文件或者采集一些应用状态信息等等,这些任务通常间隔比较短,频次比较高。随着定时任务增多,定时任务偶尔出现了积压问题,即:定时任务总是顺序执行的,无法并行执行,此时当某个定时任务卡住时,会影响其他定时任务的执行,这样的结果不是我们想看到的。
现象创建了两个定时任务
TestSchedule1 每 3 秒执行一次TestSchedule2 每 2 秒执行一次
@Scheduled(cron = "0/3 * * * * ?")
public void TestSchedule1(){
log.info("我是定时任务1");
}
@Scheduled(fixedRate = 2000)
public void TestSchedule2(){
log.info("我是定时任务2");
}
此时日志输出
2022-03-26 22:02:00.547 INFO 35776 --- [ scheduling-1] com.wozaizhe55.demo.service.TestService : 我是定时任务2 2022-03-26 22:02:02.549 INFO 35776 --- [ scheduling-1] com.wozaizhe55.demo.service.TestService : 我是定时任务2 2022-03-26 22:02:03.002 INFO 35776 --- [ scheduling-1] com.wozaizhe55.demo.service.TestService : 我是定时任务1 2022-03-26 22:02:04.549 INFO 35776 --- [ scheduling-1] com.wozaizhe55.demo.service.TestService : 我是定时任务2 2022-03-26 22:02:06.005 INFO 35776 --- [ scheduling-1] com.wozaizhe55.demo.service.TestService : 我是定时任务1 2022-03-26 22:02:06.547 INFO 35776 --- [ scheduling-1] com.wozaizhe55.demo.service.TestService : 我是定时任务2 2022-03-26 22:02:08.551 INFO 35776 --- [ scheduling-1] com.wozaizhe55.demo.service.TestService : 我是定时任务2
看着非常合理,两个定时任务都是按照既定时间间隔开始执行。
现在我们调整一下任务,让任务1的每次执行耗时 5 秒
@Scheduled(cron = "0/3 * * * * ?")
public void TestSchedule1(){
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
log.error("中断异常:{}", e);
}
log.info("我是定时任务1");
}
2022-03-26 22:16:41.009 INFO 84071 --- [ scheduling-1] com.wozaizhe55.demo.service.TestService : 我是定时任务1 2022-03-26 22:16:41.010 INFO 84071 --- [ scheduling-1] com.wozaizhe55.demo.service.TestService : 我是定时任务2 2022-03-26 22:16:41.010 INFO 84071 --- [ scheduling-1] com.wozaizhe55.demo.service.TestService : 我是定时任务2 2022-03-26 22:16:41.493 INFO 84071 --- [ scheduling-1] com.wozaizhe55.demo.service.TestService : 我是定时任务2 2022-03-26 22:16:47.001 INFO 84071 --- [ scheduling-1] com.wozaizhe55.demo.service.TestService : 我是定时任务1 2022-03-26 22:16:47.002 INFO 84071 --- [ scheduling-1] com.wozaizhe55.demo.service.TestService : 我是定时任务2 2022-03-26 22:16:47.002 INFO 84071 --- [ scheduling-1] com.wozaizhe55.demo.service.TestService : 我是定时任务2 2022-03-26 22:16:47.494 INFO 84071 --- [ scheduling-1] com.wozaizhe55.demo.service.TestService : 我是定时任务2
从日志中我们发现,定时任务2 在定时任务1结束之后连续执行了3次(间隔非常短),按照设想它的时间间隔应该是2秒才对,这样连续执行不符合咱们的设计预期。
原因定时任务2之所以连续执行了3次是因为定时任务产生了积压,从日志中可以看到执行定时任务的线程为:scheduling-1 ,且任务1 和任务 2 都是这个线程,所以当任务1执行的5秒中任务 2只能等着,任务1 结束后把积压的任务一下子执行了。
解决方法创建一个线程池,让定时任务在线程池中之行。这里先列出方案,具体实现挖个坑下次说。
- 创建一个线程池,并交给spring 管理;定时任务上添加@Async注解,指定线程池名字;



