Task定時器
定義xml定時任務(wù)配置
<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標(biāo)簽被解析為一個Task的具體實(shí)現(xiàn)類

Spring-Task結(jié)構(gòu)圖.png
調(diào)度執(zhí)行入口:ContextLifecycleScheduledTaskRegistrar
// ContextLifecycleScheduledTaskRegistrar
// 在Bean初始化之后調(diào)度
@Override
public void afterSingletonsInstantiated() {
scheduleTasks();
}
// ScheduledTaskRegistrar
// 如果配置了相應(yīng)的Tasks,則添加到Set<ScheduledTask> scheduledTasks中
protected void scheduleTasks() {
// 初始化taskScheduler,如果沒有配置task:scheduler,就會進(jìn)行初始化
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解析表達(dá)式為trigger
- tips: Trigger被定義為決定一個任務(wù)的下一次執(zhí)行時間
/**
* 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進(jìn)行解析
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來完成調(diào)度;
- (這里不談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);
// 下一次執(zhí)行窗口調(diào)用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地址