关于上一篇文章中提到的 SpringBoot 项目中当标注 @EnableScheduling 注解时会自动配置一个 ThreadPoolTaskScheduler 任务调度执行器 bean,并且 @Scheduled 的定时任务就是由该 bean 负责执行的,之前没有看过该类中的源码 , 今天正好在做定时任务好奇心的驱使下研究了一下源码:
源码路径:org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler
首先一起看一下这个类的继承关系图:
类关系中主要大部分是一些接口定义了一些规范,以及做一些初始化以及停止时的一些销毁工作 (不是真正执行定时任务的主角)。
任务执行主角:
类内部属性中有一个ScheduledExecutorService ,ScheduledExecutorService 是一个接口,也是定义些规范。 这个接口的实现类才是主要执行任务的
bean 的初始化流程(创建 ScheduledExecutorService 实现类对象):
1、ExecutorConfigurationSupport.afterPropertiesSet()
2、ExecutorConfigurationSupport.initialize()
3、ThreadPoolTaskScheduler.initializeExecutor(ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler)
4、ThreadPoolTaskScheduler.createExecutor(int poolSize, ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler)
由于 ExecutorConfigurationSupport 类中的 initializeExecutor 方法是一个抽象方法,所以是在子类中实现,也就是最终初始化是调用 ThreadPoolTaskScheduler 中的initializeExecutor 方法创建一个 ScheduledExecutorService 的实现类ScheduledThreadPoolExecutor 对象作为定时任务真正执行对象
/**
* Calls {@code initialize()} after the container applied all property values.
* @see #initialize()
*/
@Override
public void afterPropertiesSet() {
initialize();
}
/**
* Set up the ExecutorService.
*/
public void initialize() {
if (logger.isInfoEnabled()) {
logger.info("Initializing ExecutorService" + (this.beanName != null ? " '" + this.beanName + "'" : ""));
}
if (!this.threadNamePrefixSet && this.beanName != null) {
setThreadNamePrefix(this.beanName + "-");
}
this.executor = initializeExecutor(this.threadFactory, this.rejectedExecutionHandler);
}
/**
* Create the target {@link java.util.concurrent.ExecutorService} instance.
* Called by {@code afterPropertiesSet}.
* @param threadFactory the ThreadFactory to use
* @param rejectedExecutionHandler the RejectedExecutionHandler to use
* @return a new ExecutorService instance
* @see #afterPropertiesSet()
*/
protected abstract ExecutorService initializeExecutor(
ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler);
@Override
protected ExecutorService initializeExecutor(
ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
this.scheduledExecutor = createExecutor(this.poolSize, threadFactory, rejectedExecutionHandler);
if (this.removeOnCancelPolicy) {
if (this.scheduledExecutor instanceof ScheduledThreadPoolExecutor) {
((ScheduledThreadPoolExecutor) this.scheduledExecutor).setRemoveOnCancelPolicy(true);
}
else {
logger.debug("Could not apply remove-on-cancel policy - not a ScheduledThreadPoolExecutor");
}
}
return this.scheduledExecutor;
}
protected ScheduledExecutorService createExecutor(
int poolSize, ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
return new ScheduledThreadPoolExecutor(poolSize, threadFactory, rejectedExecutionHandler);
}
ScheduledThreadPoolExecutor 类关系图:
public ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue(), threadFactory, handler);
}
构造方法内仅调用了父类线程池类的构造方法进行初始化。
最后如果在 SSM 项目中想注入一个 ThreadPoolTaskScheduler 对象,在 xml 中配置
<task:scheduler id=“scheduler” pool-size=“10” /> 即可,pool-size 指定线程池的大小。
<xsd:element name="scheduler">
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines a ThreadPoolTaskScheduler instance with configurable pool size. See Javadoc
for the org.springframework.scheduling.annotation.EnableScheduling annotation for
information on a code-based alternative to this XML element.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:attribute name="id" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
The bean name for the generated ThreadPoolTaskScheduler instance.
It will also be used as the default thread name prefix.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="pool-size" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The size of the ScheduledExecutorService's thread pool. The default is 1.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>