前言
本篇文章针对上篇文章springboot异步线程,有一位大佬在评论中提出第一点是错误的,当时看到了这个问题,最近刚好有空,针对第一点的问题去搜索了不少的文章;
问题
我在文章中第一点去验证:Scheduled为单线程执行,这是错误的;正确的是,scheduled单线程执行是因为使用默认线程池核心线程数为1,如果配置默认线程池ThreadPoolTaskScheduler的核心线程数,则一样是多线程的执行,这里直接贴出了大佬的原话。
验证流程
- 在项目启动时发现初始化
taskScheduler
和asyncTaskExecutor
两个,但是我自定义了一个asyncTaskExecutor
,那么另一个怎么回事呢;
1 |
|
- 查找
taskScheduler
根据SpringBoot源码解析-Scheduled定时器的原理这篇文章里面的springboot中定时器的原理找到ScheduledAnnotationBeanPostProcessor
类,该类只是实现原理,而且是通过BeanFactory
来获取的taskScheduler
,那taskScheduler
在哪里初始化进容器的呢?
1 |
|
这里我用了一个本办法:将我上一篇文章的AsyncConfig
类中的bean改为:
1 |
|
再次启动springboot,会出现以下错误:
1 |
|
这时我们发现taskScheduler
在TaskSchedulingAutoConfiguration
类中初始化,再进入TaskSchedulingAutoConfiguration
类:
1 |
|
发现该bean使用了TaskSchedulingProperties
,再进入TaskSchedulingProperties
类,发现该类上有@ConfigurationProperties("spring.task.scheduling")
注解,到这里就可以发现taskScheduler
是可以通过properties配置文件配置参数了,下边我们看一下taskScheduler
的默认参数吧:
TaskExecutionProperties类:
private int queueCapacity = 2147483647;
private int coreSize = 8;
private int maxSize = 2147483647;
private boolean allowCoreThreadTimeout = true;
private Duration keepAlive = Duration.ofSeconds(60L);
TaskSchedulingProperties类
private int size = 1;
private String threadNamePrefix = "scheduling-";
在properties中自定义参数:
1 |
|
再来看配置后的打印信息
1 |
|
总结
Scheduled
注解默认使用taskScheduler
线程池taskScheduler
线程池使用默认属性,也就是线程只有一个,所以才会误认为Scheduled
为单线程- 如果使用默认的线程池
taskScheduler
,如果不修改默认参数,在使用中,线程出现堵塞或死循环问题会造成定时任务无法定时或者不能执行;