并发编程之定时任务&定时线程池原理解析( 三 )

delayedExecute 任务提交方法:
private void delayedExecute(RunnableScheduledFuture<?> task) {    //如果线程池已经关闭 , 则使用拒绝策略把提交任务拒绝掉 if (isShutdown())        reject(task);    else {  //与ThreadPoolExecutor不同 , 这里直接把任务加入延迟队列        super.getQueue().add(task);//使用用的DelayedWorkQueue  //如果当前状态无法执行任务 , 则取消        if (isShutdown() &&            !canRunInCurrentRunState(task.isPeriodic()) &&            remove(task))            task.cancel(false);        else         //这里是增加一个worker线程 , 避免提交的任务没有worker去执行         //原因就是该类没有像ThreadPoolExecutor一样 , woker满了才放入队列           ensurePrestart();    }}我们可以看到提交到线程池的任务都包装成了 ScheduledFutureTask , 继续往下我们再来研究下 。
ScheduledFutureTask从ScheduledFutureTask类的定义可以看出 , ScheduledFutureTask类是ScheduledThreadPoolExecutor类的私有内部类 , 继承了FutureTask类 , 并实现了RunnableScheduledFuture接口 。也就是说 , ScheduledFutureTask具有FutureTask类的所有功能 , 并实现了RunnableScheduledFuture接口的所有方法 。ScheduledFutureTask类的定义如下所示:
private class ScheduledFutureTask<V> extends FutureTask<V> implements RunnableScheduledFuture<V>ScheduledFutureTask类继承图如下:

并发编程之定时任务&定时线程池原理解析

文章插图
 
成员变量SchduledFutureTask接收的参数(成员变量):
// 任务开始的时间private long time;// 任务添加到ScheduledThreadPoolExecutor中被分配的唯一序列号private final long sequenceNumber;// 任务执行的时间间隔private final long period;//ScheduledFutureTask对象 , 实际指向当前对象本身RunnableScheduledFuture<V> outerTask = this;//当前任务在延迟队列中的索引,能够更加方便的取消当前任务int heapIndex;解析:
  • sequenceNumber:任务添加到ScheduledThreadPoolExecutor中被分配的唯一序列号 , 可以根据这个序列号确定唯一的一个任务 , 如果在定时任务中 , 如果一个任务是周期性执行的 , 但是它们的sequenceNumber的值相同 , 则被视为是同一个任务 。
  • time:下一次执行任务的时间 。
  • period:任务的执行周期 。
  • outerTask:ScheduledFutureTask对象 , 实际指向当前对象本身 。此对象的引用会被传入到周期性执行任务的ScheduledThreadPoolExecutor类的reExecutePeriodic方法中 。
  • heapIndex:当前任务在延迟队列中的索引 , 这个索引能够更加方便的取消当前任务 。
构造方法ScheduledFutureTask类继承了FutureTask类 , 并实现了RunnableScheduledFuture接口 。在ScheduledFutureTask类中提供了如下构造方法 。
ScheduledFutureTask(Runnable r, V result, long ns) { super(r, result); this.time = ns; this.period = 0; this.sequenceNumber = sequencer.getAndIncrement();}ScheduledFutureTask(Runnable r, V result, long ns, long period) { super(r, result); this.time = ns; this.period = period; this.sequenceNumber = sequencer.getAndIncrement();}ScheduledFutureTask(Callable<V> callable, long ns) { super(callable); this.time = ns; this.period = 0; this.sequenceNumber = sequencer.getAndIncrement();}FutureTask的构造方法如下:
public FutureTask(Runnable runnable, V result) { this.callable = Executors.callable(runnable, result); this.state = NEW;       // ensure visibility of callable}


推荐阅读