这是一个可以在制定一定延迟时间后或者定时进行任务调度的线程池.
ScheduledThreadPoolExecutor继承了ThreadPoolExecutor并实现了ScheduledExecutorService接口.
线程池(任务)队列是DelayedWorkQueue,和DelayedQueue(每一个节点有一个过期时间,队列首元素最快过期,出队时如果不过期短暂挂起,自旋判断)类似,是一个延迟队列.
ScheduledFutureTask是具有返回值的任务,集成自FutureTask.
FutureTask内部有一个变量state用来表示任务的状态:
NEW = 0 初始状态COMPLETING = 1 执行中NORMAL = 2 正常运行结束EXCEPTIONAL = 3 运行中异常CANCELLED = 4 任务被取消INTERRUPTING = 5 任务正在被中断INTERRUPTING = 6 任务已经被中断任务状态转换路径:
NEW-> COMPLETING -> NORMAL // 任务正常执行NEW -> COMPLETING -> EXCEPTIONAL // 执行出现异常NEW -> CANCELLED // 任务被取消NEW -> INTERRUPTING -> INTERRUPTING // 任务被中断 该方法提交一个延迟执行的任务,任务从提交时间算起延迟单位为unit的delay时间后开始执行,任务只会执行一次.
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) { // 参数校验 if (command == null || unit == null) throw new NullPointerException(); // 装饰任务,将Runnable类型的任务封装为ScheduledFutureTask对象t RunnableScheduledFuture<?> t = decorateTask(command, new ScheduledFutureTask<Void>(command, null, triggerTime(delay, unit))); // 添加到延迟队列 delayedExecute(t); return t; } 该方法的作用是当任务执行完毕后,让其延迟固定时间后再次运行.
当任务执行完毕后,让其延迟固定的时间再次执行.
任务会一致重复执行到任务运行中出现了异常,或者被取消,被关闭线程池.
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay,// 延迟开始时间 long delay,// 重复执行的时间间隔 TimeUnit unit) {// 以上两个时间的单位 // 参数校验 if (command == null || unit == null) throw new NullPointerException(); if (delay <= 0) throw new IllegalArgumentException(); // 封装为ScheduledFutureTask对象,延迟执行任务 ScheduledFutureTask<Void> sft = new ScheduledFutureTask<Void>(command, null, triggerTime(initialDelay, unit), unit.toNanos(-delay));// 这里注意是负的,说明是可重复执行的 RunnableScheduledFuture<Void> t = decorateTask(command, sft); sft.outerTask = t; // 添加任务到队列 delayedExecute(t); return t; } 当任务执行完毕后,让其延迟固定的时间再次执行,这个动作会一直重复到任务运行中抛出异常,被取消或者线程池被关闭.
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { // 参数校验 if (command == null || unit == null) throw new NullPointerException(); if (period <= 0) throw new IllegalArgumentException(); // 这里period不是负的,所以在后面的调用当中,设置的时间是time+=p,而不是time=triggerTime(-p) ScheduledFutureTask<Void> sft = new ScheduledFutureTask<Void>(command, null, triggerTime(initialDelay, unit), unit.toNanos(period)); RunnableScheduledFuture<Void> t = decorateTask(command, sft); sft.outerTask = t; delayedExecute(t); return t; }总结如下:
scheduleAtFixedRate和scheduleWithFixedDelay都是在初始delay后开始执行,scheduleAtFixedRate每次任务执行的时间理论上是固定的,不算任务执行的时间,依次是initialDelay、initialDelay+period、 initialDelay + 2 * period定点执行任务,如果一次任务的执行消耗时间过多,将延后下个任务执行;在这点上scheduleWithFixedDelay不一样,scheduleWithFixedDelay是下次任务的执行是在上次任务执行完成后的delay时间后开始。两者在任务抛异常后都会终止任务执行,另外通过cancel也可以终止任务执行。ScheduledThreadPoolExecutor可以对进入线程池的任务进行时间上的调度,有三种可选的执行方式:
schedule()方法:单次的在到一定时间之后执行任务scheduleWithFixedDelay()方法:多次以某一个时间间隔重复的在一段时间之后执行某任务,scheduleAtFixedRate()方法:与2类似,但计算时间间隔不考虑程序运行的时间.