一、Spring scheduling包结构
包位于spring-context中,共包含如图所示的几个包。
二、scheduling包
本文着重讲解TaskScheduler、Trigger、TriggerContext。
(1) TaskScheduler
这个接口有以下方法:
//按照Trigger指定的下一次的执行时间执行一个任务ScheduledFuture schedule(Runnable task, Trigger trigger); //按照指定的时间执行任务 ScheduledFuture schedule(Runnable task, Date startTime); //按照固定的时间间隔执行任务,第一次开始执行的时间由startTime指定,period指定执行间隔//时间间隔指每次任务开始的时间ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period); //按照固定的时间间隔执行任务,period指定执行间隔,时间间隔指每次任务开始的时间 ScheduledFuture scheduleAtFixedRate(Runnable task, long period); //按照固定的时间间隔执行任务,时间间隔指任务的结束到下一次任务开始之间的时间,delay指定时间//间隔,startTime指定第一次任务的开始时间 ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long delay); //按照固定的时间间隔执行任务,时间间隔指任务的结束到下一次任务开始之间的时间,delay指定时间//间隔 ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay);
(2)Trigger
这个接口只有一个方法
Date nextExecutionTime(TriggerContext triggerContext);
这个方法用于获得任务的下一次执行日期
(3)TriggerContext
这个接口提供三个方法,
//获得上次任务计划执行的日期 Date lastScheduledExecutionTime(); //获得上次任务实际的执行日期 Date lastActualExecutionTime(); //获得上次任务的完成日期 Date lastCompletionTime();
三、scheduling.concurrent包
(1)ConcurrentTaskExecutor
spring中的并发任务执行器,实现了java.util.concurrent中的Executor接口。
类中有一个Executor对象和TaskExecutorAdapter对象。
TaskExecutorAdapter位于org.springframework.core.task.support包中,
是一个Executor适配器,实现了Executor接口,其中有一个Executor对象。
当注入的Executor实现了ExecutorService接口时,直接调用Executor执行,并返回一个Future。如果未实现ExecutorService接口,则创建一个FutureTask,并利用Executor执行该FutureTask,并返回该FutureTask。
(2)ConcurrentTaskScheduler
ConcurrentTaskScheduler实现了TaskScheduler接口,继承了ConcurrentTaskExecutor类。
ConcurrentTaskScheduler中有一个ScheduledExecutorService对象,当不向ConcurrentTaskScheduler中注入ScheduledExecutorService时,类内部会利用Executors.newSingleThreadScheduledExecutor()创建一个单线程的ScheduledExecutorService对象。
public ScheduledFuture schedule(Runnable task, Trigger trigger) { try { ErrorHandler errorHandler = (this.errorHandler != null ? this.errorHandler : TaskUtils.getDefaultErrorHandler(true)); return new ReschedulingRunnable(task, trigger, this.scheduledExecutor, errorHandler).schedule(); } catch (RejectedExecutionException ex) { throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex); } }
schedule(Runnable task, Trigger trigger)的实现如上述代码。
方法内部新建一个ReschedulingRunnable类,通过构造方法注入任务、Trigger、ScheduledExecutorService等。
public ReschedulingRunnable(Runnable delegate, Trigger trigger, ScheduledExecutorService executor, ErrorHandler errorHandler) { super(delegate, errorHandler); this.trigger = trigger; this.executor = executor; }
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); return this; } }
然后通过调用上述方法执行计划任务。
ReschedulingRunnable类内部覆盖了run()方法。
@Override public void run() { Date actualExecutionTime = new Date(); super.run(); Date completionTime = new Date(); synchronized (this.triggerContextMonitor) { this.triggerContext.update(this.scheduledExecutionTime, actualExecutionTime, completionTime); if (!this.currentFuture.isCancelled()) { schedule(); } } }