什么是ScheduledThreadPoolExecutor?
ScheduledThreadPoolExecutor是JUC中用于定时任务调用 和周期性任务执行 的核心类。它继承于ThreadPoolExecutor,与普通线程池不同的是,它使用的BlockingQueue是DelayedWorkQueue,这使得它能够按照时间顺序调度任务。
ScheduledThreadPoolExecutor内部原理
ScheduledFutureTask
ScheduledThreadPoolExecutor 将任务封装成 ScheduledFutureTask,然后放入一个特殊的阻塞队列 DelayedWorkQueue。
ScheduledFutureTask是具有返回值的任务, 继承自FutureTask。FutureTask的内部有 一个变量state用来表示任务的状态, 一开始状态为NEW, 所有状态为
java
private static final int NEW = 0; // 初始状态,任务尚未开始或尚未完成
private static final int COMPLETING = 1; // 正在完成,结果已设置但尚未通知等待线程
private static final int NORMAL = 2; // 正常完成,任务执行成功并设置了结果
private static final int EXCEPTIONAL = 3; // 异常完成,任务执行过程中抛出了异常
private static final int CANCELLED = 4; // 已取消,任务在完成前被取消(未响应中断)
private static final int INTERRUPTING = 5; // 正在中断,任务已被中断但中断操作尚未完成
private static final int INTERRUPTED = 6; // 已中断,任务已被中断且中断操作已完成
并且ScheduledFutureTask内部还有一个变量period用来表示任务的类型:
period == 0:一次性任务(非周期性)。period > 0:scheduleAtFixedRate,固定频率。period < 0:scheduleWithFixedDelay,固定延迟。
ScheduledThreadPoolExecutor方法
构造方法
java
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE,
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue());
}
其中DelayedWorkQueue是一个无界队列,因此maximumPoolSize=Integer.MAX_VALUE这个参数没有意义。
重要方法
ScheduledThreadPoolExecutor有三个重要的函数
schedule(Runnable/Callable, delay, TimeUnit)
- 在指定的
delay时间后,执行一次任务。 - 返回
ScheduledFuture,可用于取消任务或获取结果。
scheduleAtFixedRate(Runnable, initialDelay, period, TimeUnit)
- 在
initialDelay后开始第一次执行,然后每隔period时间执行一次。 - 这里的
period是指两次任务开始执行的时间间隔。 - 如果某次任务执行时间超过了
period,下一次执行会立即开始,不会并发执行同一个任务(同一个任务实例不会同时运行两次)。 - 适合"固定频率"的场景,如每5秒采集一次状态。
scheduleWithFixedDelay(Runnable, initialDelay, delay, TimeUnit)
- 在
initialDelay后开始第一次执行,之后在上一次执行完成后,等待delay时间再执行下一次。 delay是指前一次执行结束到下一次执行开始的间隔。- 适合"固定间隔等待"的场景,如发送完一条消息后等 10 秒再发下一条。