20220726_Jdk调度线程服务ScheduledThreadPoolExecutor学习笔记.md
1概述
1.1ScheduledThreadPoolExecutor类图结构
从类图结构我们看出,ScheduledThreadPoolExecutor继承了ThreadPoolExecutor并实现了ScheduledExecutorService接口。
ThreadPoolExecutor具备线程池的创建管理功能。
提交给队列的任务本质都实现了Runnable接口。每个线程都被封装成Worker,通过getTask进行任务的获取、通过委托runWorker进行任务运行。
ScheduledExecutorService定义了周期性或一次性任务的执行接口。
1.2ThreadPoolExecutor基类
定义了模板方法,getTask()。
// C:\Program Files\Java\jdk1.8.0_60\src.zip!\java\util\concurrent\ThreadPoolExecutor.java
// 定义线程池可重入锁
// 线程的并发管理(创建、中断、销毁等)
private final ReentrantLock mainLock = new ReentrantLock();
1.3ScheduledThreadPoolExecutor子类
// 构造ScheduledThreadPoolExecutor
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize, // max
long keepAliveTime, // 0
TimeUnit unit, // ns
BlockingQueue workQueue) { // 阻塞队列
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
1.3.1ScheduledFutureTask
封装的某个任务并提交到线程池。
private class Scheduled FutureTask
extends FutureTask implements RunnableScheduledFuture {
public interface Runnable Scheduled Future extends RunnableFuture, ScheduledFuture {
public interface ScheduledFuture extends Delayed, Future { // 从这里我们可以看出,Scheduled本质继承了Delayed接口
public interface Runnable uture extends Runnable, Future {
1.3.2DelayedWorkQueue
延迟队列,实现小顶堆,本质也是BlockingQueue,作为线程池的workQueue。用于从队列DelayedWorkQueeu中取任务ScheduledFutureTask。
static class DelayedWorkQueue extends AbstractQueue
implements BlockingQueue {
// 这里队列的本质为数组,RunnableScheduledFuture>[]extends Delayed
private RunnableScheduledFuture>[] queue =
new RunnableScheduledFuture>[INITIAL_CAPACITY];
// 获取队列中的任务
// 因为DelayedWorkQueue是线程池共用的,所以加锁,确保并发安全
private final ReentrantLock lock = new ReentrantLock();
// peek
public RunnableScheduledFuture> peek() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return queue[0];
} finally {
lock.unlock();
}
}
1.3.2.1任务添加offer(put、add)
public void put(Runnable e) {
offer(e);
}
public boolean add(Runnable e) {
return offer(e);
}
public boolean offer(Runnable e, long timeout, TimeUnit unit) {
return offer(e);
}
public boolean offer(Runnable x) {
if (x == null)
throw new NullPointerException();
RunnableScheduledFuture> e = (RunnableScheduledFuture>)x;
final ReentrantLock lock = this.lock;
lock.lock();
try {
int i = size;
if (i >= queue.length)
grow();
size = i + 1;
if (i == 0) {
queue[0] = e;
setIndex(e, 0);
} else {
siftUp(i, e);
}
if (queue[0] == e) {
leader = null;
available.signal();
}
} finally {
lock.unlock();
}
return true;
}
1.3.2.2任务获取takde vs poll
// 无限等待信号到来
public RunnableScheduledFuture> take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly(); // 可中断的锁
try {
for (;;) { // 无限循环
RunnableScheduledFuture> first = queue[0];
if (first == null)
available.await(); // 没有则等待信号
else {
long delay = first.getDelay(NANOSECONDS);
if (delay <= 0)
return finishPoll(first);
first = null; // don't retain ref while waiting
if (leader != null)
available.await(); // 没有则等待信号
else {
Thread thisThread = Thread.currentThread();
leader = thisThread; // 记录当前线程
try {
available.awaitNanos(delay); // 等待指定的时间
} finally {
if (leader == thisThread)
leader = null;
}
}
}
}
} finally {
if (leader == null && queue[0] != null)
available.signal();
lock.unlock();
}
}
// 不等待,没有则直接返回
public RunnableScheduledFuture> poll() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
RunnableScheduledFuture> first = queue[0];
if (first == null || first.getDelay(NANOSECONDS) > 0)
return null;
else
return finishPoll(first);
} finally {
lock.unlock();
}
}
// 等待,指定时间 by awaitNanos
public RunnableScheduledFuture> poll(long timeout, TimeUnit unit)
throws InterruptedException {
long nanos = unit.toNanos(timeout);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
for (;;) {
RunnableScheduledFuture> first = queue[0];
if (first == null) {
if (nanos <= 0)
return null;
else
nanos = available.awaitNanos(nanos);
} else {
long delay = first.getDelay(NANOSECONDS);
if (delay <= 0)
return finishPoll(first);
if (nanos <= 0)
return null;
first = null; // don't retain ref while waiting
if (nanos < delay || leader != null)
nanos = available.awaitNanos(nanos);
else {
Thread thisThread = Thread.currentThread();
leader = thisThread;
try {
long timeLeft = available.awaitNanos(delay);
nanos -= delay - timeLeft;
} finally {
if (leader == thisThread)
leader = null;
}
}
}
}
} finally {
if (leader == null && queue[0] != null)
available.signal();
lock.unlock();
}
}
1.4外部任务管理
1.4.1任务添加ScheduledThreadPoolExecutor#delayedExecute
将延时任务添加到DelayedWorkQueue中。
public ScheduledFuture> schedule(Runnable command,
long delay,
TimeUnit unit) {
if (command == null || unit == null)
throw new NullPointerException();
// 这里,decorateTask啥也没做
RunnableScheduledFuture> t = decorateTask(command,
new ScheduledFutureTask(command, null,
triggerTime(delay, unit)));
delayedExecute(t);
return t;
}
private void delayedExecute(RunnableScheduledFuture> task) {
if (isShutdown())
reject(task);
else {
super.getQueue().add(task);
1.4.2任务获取ThreadPoolExecutor#getTask
重点:getTask是一个模板方法。
C:\Program Files\Java\jdk1.8.0_60\src.zip!\java\util\concurrent\ThreadPoolExecutor.java
private Runnable getTask() {
try {
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
1.4.2.1DelayedWorkQueue#Take(具体参看1.3.2.2)
1.4.2.2DelayedWorkQueue#Pool(具体参看1.3.2.2)