springboot定时任务线程阻塞踩坑
场景描述
在使用Springboot
整合定时任务,发现当某个定时任务执行出现执行时间过长的情况时会阻塞其他定时任务的执行。
问题定位
后续通过翻查Springboot
的文档以及打印日志(输出当前线程信息)得知问题是由于Springboot
默认使用只有1
个线程的单线程池处理定时任务。
问题复盘
需要注意示例的Springboot
版本为2.1.3.RELEASE
。
@Component @Log4j2 public class ScheduledTask { @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; } } @Scheduled(cron = "0/5 * * * * ?") public void task2() { log.info("I am task22222222, current thread: {}", Thread.currentThread()); } }
2019-04-24 17:11:15.008 INFO 16868 --- [ scheduling-1] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[scheduling-1,5,main] 2019-04-24 17:11:15.009 INFO 16868 --- [ scheduling-1] com.example.demo.task.ScheduledTask : I am task11111111, current thread: Thread[scheduling-1,5,main] 2019-04-24 17:11:25.009 INFO 16868 --- [ scheduling-1] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[scheduling-1,5,main] 2019-04-24 17:11:30.002 INFO 16868 --- [ scheduling-1] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[scheduling-1,5,main] 2019-04-24 17:11:30.003 INFO 16868 --- [ scheduling-1] com.example.demo.task.ScheduledTask : I am task11111111, current thread: Thread[scheduling-1,5,main] 2019-04-24 17:11:40.004 INFO 16868 --- [ scheduling-1] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[scheduling-1,5,main]
由结果可见,task1与task2由同一个线程Thread[scheduling-1,5,main]执行,也即该定时任务默认使用单线程,并且由于task1阻塞了10s,导致本应5s执行一次的定时任务10s才执行一次。
解决方法
由于使用的Springboot
版本为2.1.3.RELEASE
,所以有两种方法解决这个问题
使用Springboot配置
在配置文件中可以配置定时任务可用的线程数:
## 配置可用线程数为10
spring.task.scheduling.pool.size=10
自定义定时任务的线程池
使用自定义的线程池代替默认的线程池
/** * 定时任务配置类 * @author RJH * create at 2019-03-29 */ @Configuration public class ScheduleConfig { /** * 此处方法名为Bean的名字,方法名无需固定 * 因为是按TaskScheduler接口自动注入 * @return */ @Bean public TaskScheduler taskScheduler(){ // Spring提供的定时任务线程池类 ThreadPoolTaskScheduler taskScheduler=new ThreadPoolTaskScheduler(); //设定最大可用的线程数目 taskScheduler.setPoolSize(10); return taskScheduler; } }
作者:森林木马
-------------------------------------------
特此声明:所有评论和私信都会在第一时间回复。也欢迎朋友们指正错误,共同进步!
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!
个性签名:好记性不如勤随笔,好随笔还请多关注!