Task定时器
定义xml定时任务配置
<task:scheduler id="scheduler" pool-size="3" />
<bean id="task" class="task.Task"/>
<task:scheduled-tasks scheduler="scheduler">
<task:scheduled ref="task" method="print" cron="0/5 * * * * ?"/>
</task:scheduled-tasks>
- 配置好xml后,Spring将其解析成为BeanDefinition
其中task:scheduled标签被解析为一个Task的具体实现类
Spring-Task结构图.png
调度执行入口:ContextLifecycleScheduledTaskRegistrar
// ContextLifecycleScheduledTaskRegistrar
// 在Bean初始化之后调度
@Override
public void afterSingletonsInstantiated() {
scheduleTasks();
}
// ScheduledTaskRegistrar
// 如果配置了相应的Tasks,则添加到Set<ScheduledTask> scheduledTasks中
protected void scheduleTasks() {
// 初始化taskScheduler,如果没有配置task:scheduler,就会进行初始化
if (this.taskScheduler == null) {
this.localExecutor = Executors.newSingleThreadScheduledExecutor();
this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor);
}
if (this.triggerTasks != null) {
for (TriggerTask task : this.triggerTasks) {
addScheduledTask(scheduleTriggerTask(task));
}
}
if (this.cronTasks != null) {
for (CronTask task : this.cronTasks) {
addScheduledTask(scheduleCronTask(task));
}
}
if (this.fixedRateTasks != null) {
for (IntervalTask task : this.fixedRateTasks) {
addScheduledTask(scheduleFixedRateTask(task));
}
}
if (this.fixedDelayTasks != null) {
for (IntervalTask task : this.fixedDelayTasks) {
addScheduledTask(scheduleFixedDelayTask(task));
}
}
}
下面以CronTask为例:
CronTask解析表达式为trigger
- tips: Trigger被定义为决定一个任务的下一次执行时间
/**
* Create a new {@code CronTask}.
* @param runnable the underlying task to execute
* @param expression the cron expression defining when the task should be executed
*/
public CronTask(Runnable runnable, String expression) {
this(runnable, new CronTrigger(expression));
}
/**
* Build a {@link CronTrigger} from the pattern provided in the default time zone.
* @param expression a space-separated list of time fields, following cron
* expression conventions
*/
public CronTrigger(String expression) {
this.sequenceGenerator = new CronSequenceGenerator(expression);
}
···
// 最后到CronSequenceGenerator进行解析
private void doParse(String[] fields) {
setNumberHits(this.seconds, fields[0], 0, 60);
setNumberHits(this.minutes, fields[1], 0, 60);
setNumberHits(this.hours, fields[2], 0, 24);
setDaysOfMonth(this.daysOfMonth, fields[3]);
setMonths(this.months, fields[4]);
setDays(this.daysOfWeek, replaceOrdinals(fields[5], "SUN,MON,TUE,WED,THU,FRI,SAT"), 8);
if (this.daysOfWeek.get(7)) {
// Sunday can be represented as 0 or 7
this.daysOfWeek.set(0);
this.daysOfWeek.clear(7);
}
}
通过ReschedulingRunnable来完成调度;
- (这里不谈EnterpriseConcurrentTriggerScheduler)
ReschedulingRunnable: 其父类DelegatingErrorHandlingRunnable implements 了 Runnable
@Nullable
public ScheduledFuture<?> schedule() {
synchronized (this.triggerContextMonitor) {
this.scheduledExecutionTime = this.trigger.nextExecutionTime(this.triggerContext);
if (this.scheduledExecutionTime == null) {
return null;
}
long initialDelay = this.scheduledExecutionTime.getTime() - System.currentTimeMillis();
this.currentFuture = this.executor.schedule(this, initialDelay, TimeUnit.MILLISECONDS);
// 下一次执行窗口调用this(ReschedulingRunnable)
return this;
}
}
@Override
public void run() {
Date actualExecutionTime = new Date();
super.run();
Date completionTime = new Date();
synchronized (this.triggerContextMonitor) {
Assert.state(this.scheduledExecutionTime != null, "No scheduled execution");
this.triggerContext.update(this.scheduledExecutionTime, actualExecutionTime, completionTime);
if (!obtainCurrentFuture().isCancelled()) {
schedule();
}
}
}
参考:
Seaswalker的Spring-analysis:
github地址