一、Spring scheduling包结构

包位于spring-context中,共包含如图所示的几个包。Spring Scheduling详解_计划任务

二、scheduling包

Spring Scheduling详解_计划任务_02

 本文着重讲解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包

Spring Scheduling详解_spring_03

(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();
            }
        }
    }