scheduled定时任务不执行,springboot schedule定时任务
00-1010一、问题描述二。场景再现三。方案一:使用@Async注释实现异步任务二。手动设置调度任务IV的线程池大小。摘要
00-1010在最近的项目中发现了一个问题。计划每天早上4:40执行一次计划任务,注释:@ @Scheduled(cron="0 40 4 * *?"),cron表达式显然没有问题,但是这个定时任务总是不按时执行,有时候要等到8点以后,有时候9点以后才执行。查了一下,原来这个计时方法默认是单线程执行的。正好我这里有多个定时任务,其中一个在4:40之前比较耗时,所以4336040的任务只能在前一个任务完成的时候触发,所以我要手动设置定时任务为多线程。
00-1010项目描述:使用Springboot开发设置两个预定任务,每5s执行一次,打印出执行代码如下:
@ Component @ log 4j 2 public class Scheduled task { @ Scheduled(cron= 0/5 * * * *?)public void task1()抛出InterruptedException { log.info(我是task11111111,当前线程: {} ,thread . current thread());While (true) {//模拟耗时任务,阻塞10s hread . sleep(10000);打破;} } @Scheduled(cron=0/5 * * * *?)public void task2() { log.info(我是task22222222,当前线程: {} ,thread . current thread());}}执行结果如下:
2019-04-24 17:11:15.008 INFO 16868-[scheduling-1]com . example . demo . task . scheduled task :我是task 222222222,当前线程: Thread[scheduling-1,5,main]2019-04-24 173:11:15.009 INFO 16868-[scheduling-1
从结果中可以看出,task1和task2是由同一个线程[scheduling-1,5,main]执行的,也就是说这个调度的任务默认使用了单个线程,而且因为task1被阻塞了10s,所以本应该5s执行一次的调度任务在10s内只执行了一次。
00-1010网上有很多解决方案。这里有两个。
00-1010这种方式比较简单。将@Async添加到计划任务中。
注解,注意:需启动类配合加上 @EnableAsync才会生效
代码如下:
@Component@Log4j2public class ScheduledTask { @Async @Scheduled(cron = "0/5 * * * * ?") public void task1() throws InterruptedException { log.info("I am task11111111, current thread: {}", Thread.currentThread()); while (true) { //模拟耗时任务,阻塞10s Thread.sleep(10000); break; } } @Async @Scheduled(cron = "0/5 * * * * ?") public void task2() { log.info("I am task22222222, current thread: {}", Thread.currentThread()); }}
运行结果:
2019-04-24 17:03:00.024 INFO 2152 --- [ task-1] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[task-1,5,main]2019-04-24 17:03:00.024 INFO 2152 --- [ task-2] com.example.demo.task.ScheduledTask : I am task11111111, current thread: Thread[task-2,5,main]2019-04-24 17:03:05.001 INFO 2152 --- [ task-3] com.example.demo.task.ScheduledTask : I am task11111111, current thread: Thread[task-3,5,main]2019-04-24 17:03:05.001 INFO 2152 --- [ task-4] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[task-4,5,main]2019-04-24 17:03:10.002 INFO 2152 --- [ task-5] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[task-5,5,main]2019-04-24 17:03:10.003 INFO 2152 --- [ task-6] com.example.demo.task.ScheduledTask : I am task11111111, current thread: Thread[task-6,5,main]
由运行日志可见,定时每5s执行一次已生效,且每次任务使用的线程不一样,也即实现了多线程执行定时任务,不会出现任务等待现象。此方式据说默认线程池大小为100,要是任务不多的话有点大材小用了,所以我觉得第二种方式比较好。
方案二:手动设置定时任务的线程池大小
定时任务代码部分还原,不使用@Async注解,新增启动代码配置:
@Configurationpublic class AppConfig implements SchedulingConfigurer { @Bean public Executor taskExecutor() { //指定定时任务线程数量,可根据需求自行调节 return Executors.newScheduledThreadPool(3); } @Override public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) { scheduledTaskRegistrar.setScheduler(taskExecutor()); }}
运行结果如下:
2019-04-24 17:26:15.008 INFO 2164 --- [pool-1-thread-2] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[pool-1-thread-2,5,main]2019-04-24 17:26:15.008 INFO 2164 --- [pool-1-thread-1] com.example.demo.task.ScheduledTask : I am task11111111, current thread: Thread[pool-1-thread-1,5,main]2019-04-24 17:26:20.002 INFO 2164 --- [pool-1-thread-2] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[pool-1-thread-2,5,main]2019-04-24 17:26:25.001 INFO 2164 --- [pool-1-thread-2] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[pool-1-thread-2,5,main]2019-04-24 17:26:30.001 INFO 2164 --- [pool-1-thread-1] com.example.demo.task.ScheduledTask : I am task11111111, current thread: Thread[pool-1-thread-1,5,main]2019-04-24 17:26:30.001 INFO 2164 --- [pool-1-thread-3] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[pool-1-thread-3,5,main]2019-04-24 17:26:35.001 INFO 2164 --- [pool-1-thread-3] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[pool-1-thread-3,5,main]
由结果可见,第二种方式也实现了多线程任务调度。
四. 总结
两种方式各有优缺点:
比较方案一方案二优点注解方式使用简单,代码量少配置灵活,线程数可控缺点线程数不可控,可能存在资源浪费需要增加编码留个坑,从日志上看@Async方式针对同一任务也是异步的,也即task1每5s会执行一次,但是方式二貌似对同一个任务不会生效,task1执行的时候需等待上一次执行结束才会触发,并没有每5s执行一次。关于这个现象,下次再琢磨…
参考链接:https://segmentfault.com/a/1190000015267976
到此这篇关于Spring多定时任务@Scheduled执行阻塞问题解决的文章就介绍到这了,更多相关Spring多定时任务阻塞内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。