由于工作上需求的需要,需要动态控制定时任务的执行时机,这块一开始在使用的时候不太不清楚实现原理。
后面专门去看了一下源码。
class ReschedulingRunnable extends DelegatingErrorHandlingRunnable implements ScheduledFuture<Object> {
@Override
public void run() {
Date actualExecutionTime = new Date();
1.super.run其实就是我们自定义的要执行的方法
super.run();
Date completionTime = new Date();
synchronized (this.triggerContextMonitor) {
Assert.state(this.scheduledExecutionTime != null, "No scheduled execution");
this.triggerContext.update(this.scheduledExecutionTime, actualExecutionTime, completionTime);
2.查看任务是否已经被取消
if (!obtainCurrentFuture().isCancelled()) {
3.执行完了进行下一次调度
schedule();
}
}
}
@Nullable
public ScheduledFuture<?> schedule() {
synchronized (this.triggerContextMonitor) {
4.通过触发器获取下次执行时间
this.scheduledExecutionTime = this.trigger.nextExecutionTime(this.triggerContext);
if (this.scheduledExecutionTime == null) {
return null;
}
5.由于是通过延时调用,通过下次执行时间就可以得知延时多久执行,再次执行
long initialDelay = this.scheduledExecutionTime.getTime() - System.currentTimeMillis();
this.currentFuture = this.executor.schedule(this, initialDelay, TimeUnit.MILLISECONDS);
return this;
}
}
}
从整个过程来看,其实分为好几步。
1.执行定时器任务的run方法(可以理解为业务方法)
2.判断任务是否被取消
3.完成之后进行下一次调度
4.通过触发器获取下次执行时间
5.计算出延时执行时间
6.执行
。。。循环回到1,2,3
那么如何实现动态调度?
从源码得知,第4点,每次执行都是通过触发器获取下次执行时间,所以我们只需要将cron表达式持久化,让触发器每次都从数据库里面去读最新的cron表达式,根据新的cron表达式就可以计算出下次的执行时间。
这样子就可以做到动态调度了。
如何动态修改定时任务的调度呢
最后如果要支持定时任务的新增 删除以及分布式的话,可以考虑使用quartz。这个组件支持更多的功能
网友评论