ScheduledThreadPoolExecutor 继承自 ThreadPoolExecutor。它主要用来在给定的延迟以后运行任务,或者按期执行任务。ScheduledThreadPoolExecutor 的功能与 Timer 相似,但 Timer 对应的是单个后台线程,而 ScheduledThreadPoolExecutor 能够在构造函数中指定多个对应的后台线程数。java
Timer | ScheduledThreadPoolExecutor |
---|---|
单线程 | 多线程 |
单个任务执行时间影响其余任务调度 | 多线程,不会影响 |
基于绝对时间 | 基于相对时间 |
一旦执行任务出现异常不会捕获,其余任务得不到执行 | 多线程,单个任务的执行不会影响其余线程 |
ScheduledThreadPoolExecutor 的结构和 Timer 相似,也是由 DelayedWorkQueue、ThreadPoolExecutor、ScheduledFutureTask 三部分组成。DelayedWorkQueue 是一个无界队列,因此 ThreadPoolExecutor 的 maximumPoolSize 在 ScheduledThreadPoolExecutor 中没有什么意义(设置 maximumPoolSize 的大小没有什么效果)。数据结构
ScheduledThreadPoolExecutor 的执行主要分为两大部分。多线程
1)当调用 ScheduledThreadPoolExecutor#scheduleAtFixedRate() 方法或者 scheduleWithFixedDelay() 方法时,会向 ScheduledThreadPoolExecutor#DelayedWorkQueue 添加一个实现了 RunnableScheduledFutur 接口的 ScheduledFutureTask。函数
2)线程池中的线程从 DelayedWorkQueue 中获取 ScheduledFutureTask,而后执行任务。源码分析
schedule、scheduleAtFixedRate、scheduleWithFixedDelay 只是将任务设置执行时间后添加到线程池队列中去了。线程
ublic ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { if (command == null || unit == null) throw new NullPointerException(); if (period <= 0) throw new IllegalArgumentException(); 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; } 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<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 void run() { boolean periodic = isPeriodic(); if (!canRunInCurrentRunState(periodic)) // 线程池关闭时是否断续执行定时任务 cancel(false); else if (!periodic) // 只执行一次 ScheduledFutureTask.super.run(); else if (ScheduledFutureTask.super.runAndReset()) { // 周期性执行 setNextRunTime(); // 下一次执行时间 reExecutePeriodic(outerTask); // 从新添加到任务队列中 } }
参考:code
天天用心记录一点点。内容也许不重要,但习惯很重要!blog