ThreadPoolExecutor
重要属性字段
java
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
// runState is stored in the high-order bits
private static final int RUNNING = -1 << COUNT_BITS;
private static final int SHUTDOWN = 0 << COUNT_BITS;
private static final int STOP = 1 << COUNT_BITS;
private static final int TIDYING = 2 << COUNT_BITS;
private static final int TERMINATED = 3 << COUNT_BITS;
- ctl是一个原子整数类,包含了2个概念:线程的有效数量(workerCount);运行状态(runState 运行、关闭等)。一个32bit位的int类型是如何包含这2个概念的呢?答案就是把32位拆成2部分,高3位标识runState,低29位标识线程数量。
- COUNT_BITS 值是29
- CAPACITY 容量(1<<29)-1 //00011111_11111111_11111111_11111111
- RUNNING 左移29位 -1 << COUNT_BITS //11100000_00000000_00000000_00000000 表示接受新任务并处理排队的任务
- SHUTDOWN 左移29位 0 << COUNT_BITS // 0b00000000_00000000_00000000_00000000 表示不接受新任务,但处理排队的任务
- STOP 左移29位 1 << COUNT_BITS // 0b00100000_00000000_00000000_00000000 表示不接受新任务,不处理排队的任务,并中断正在进行的任务
- TIDYING 左移2位 2 << COUNT_BITS // 0b01000000_00000000_00000000_00000000 表示所有任务都已终止,workerCount 为零,转换到状态的线程将运行 terminated()
- TERMINATED 左移三位 3 << COUNT_BITS// 0b01100000_00000000_00000000_00000000 terminated()
- 状态转换:RUNNING -> SHUTDOWN 在调用 shutdown() 时,可能隐式在 finalize() 中;(RUNNING or SHUTDOWN) -> STOP 调用 shutdownNow() 时;SHUTDOWN -> TIDYING 当 queue 和 pool 都为空时; STOP -> TIDYING 当 pool 为空时;TIDYING -> TERMINATED当 terminated()钩子方法完成时
主要构造函数
arduino
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
}
- corePoolSize 核心线程数。要保留在池中的线程数,即使它们处于空闲状态,除非设置了code allowCoreThreadTimeOut
- maximumPoolSize 最大线程数。池中允许的最大线程数
- keepAliveTime 存活时间。当线程数大于核心线程数时,这是多余的空闲线程在终止之前等待新任务的最长时间。
- unit 时间单位。keepAliveTime参数的时间单位
- workQueue 工作队列。用于在执行任务之前保留任务的队列。execute()方法提交的Runnable任务
- threadFactory 线程工厂。生产线程的工厂
- handler 拒绝策略。队列容量不够,工作线程大于等于最大线程数
Worker 对象
- 继承了同步器实现了Runnable
java
private final class Worker
extends AbstractQueuedSynchronizer
implements Runnable
继承AbstractQueuedSynchronizer实现锁的机制,确保任务执行期间不被别的线程干扰。
2.属性字段
- final Thread thread;执行任务的线程
- Runnable firstTask;初始任务
- volatile long completedTasks;记录该worker完成的任务数
- 构造方法
scss
Worker(Runnable firstTask) {
//状态设置为-1
//interruptIfStarted()方法的时候会判断>=0才会中断
setState(-1); // inhibit interrupts until runWorker
//任务
this.firstTask = firstTask;
//线程池构建的worker
this.thread = getThreadFactory().newThread(this);
}
- 方法
isHeldExclusively()
typescript
protected boolean isHeldExclusively() {
return getState() != 0;
}
判断当前线程是否持有锁,0 表示解锁状态, 1 表示持有锁
tryAcquire(int unused)
加锁方法
arduino
protected boolean tryAcquire(int unused) {
//CAS设置锁的状态为1
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
tryRelease(int unused)
解锁方法
java
protected boolean tryRelease(int unused) {
setExclusiveOwnerThread(null);
//设置为0,释放锁
setState(0);
return true;
}
interruptIfStarted()
中断线程
scss
void interruptIfStarted() {
Thread t;
if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
}
}
}
runWorker(this)
执行任务
csharp
public void run() {
//由worker构造方法 this.thread = getThreadFactory().newThread(this); 构建的线程启动后调用
runWorker(this);
}
java
final void runWorker(Worker w) {
//获取当前线程
Thread wt = Thread.currentThread();
//获取初始任务
Runnable task = w.firstTask;
//清空初始任务
w.firstTask = null;
//释放锁将初始任务状态-1改为0,允许中断
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
//循环获取任务
while (task != null || (task = getTask()) != null) {
//加锁,任务执行期间不受其他线程干扰
w.lock();
// If pool is stopping, ensure thread is interrupted;
// if not, ensure thread is not interrupted. This
// requires a recheck in second case to deal with
// shutdownNow race while clearing interrupt
//runStateAtLeast(ctl.get(), STOP) 线程池是STOP TIDYING TERMINATED等状态
//Thread.interrupted() 当前线程中断成功
// 并且 runStateAtLeast(ctl.get(), STOP))) 线程池是STOP TIDYING TERMINATED等状态
//并且 !wt.isInterrupted() 没有中断成功 再执行wt.interrupt();
if ((runStateAtLeast(ctl.get(), STOP)
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
//中断线程
wt.interrupt();
try {
//任务执行前模板方法,可扩展
beforeExecute(wt, task);
Throwable thrown = null;
try {
//执行任务 也就是业务代码里面的逻辑
task.run();
} catch (RuntimeException x) {
thrown = x; throw x;
} catch (Error x) {
thrown = x; throw x;
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
//任务执行后模板方法,可扩展
afterExecute(task, thrown);
}
} finally {
//帮助垃圾回收
task = null;
//worker 执行的任务计数
w.completedTasks++;
//释放锁 执行完之后释放锁,这时候这个worker就可以继续执行任务了
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
java
private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out?
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
//不是正常状态(RUNNING)或队列是空的
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
//减小线程数
decrementWorkerCount();
return null;
}
//工作线程数量
int wc = workerCountOf(c);
// Are workers subject to culling?
//是否容许核心线程超市或者工作线程数大于核心线程数
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
//判断是否需要减少线程数(线程数超过最大值或超时且无任务)
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
//CAS 线程数减一
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
try {
//从队列获取任务
Runnable r = timed ?
//允许核心线程超时或者线程池数大于核心线程数 keepAliveTime时间内获取任务
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
//获取任务 没任务时等待任务
workQueue.take();
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}
scss
private void processWorkerExit(Worker w, boolean completedAbruptly) {
//因一场退出,减少线程数
if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
decrementWorkerCount();
final ReentrantLock mainLock = this.mainLock;
//获取锁 因为不只是一个worker线程 防止互相干扰
mainLock.lock();
try {
//累加线程池worker完成的任务数
completedTaskCount += w.completedTasks;
//移除工作线程
workers.remove(w);
} finally {
//释放锁 给别的worker执行
mainLock.unlock();
}
//尝试终止线程池
tryTerminate();
int c = ctl.get();
//线程池状态为RUNNING或SHUTDOWN
if (runStateLessThan(c, STOP)) {
//正常退出
if (!completedAbruptly) {
int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
// 允许核心线程超时且队列不为空 退出
if (min == 0 && ! workQueue.isEmpty())
min = 1;
//至少还有一个工作线程
if (workerCountOf(c) >= min)
return; // replacement not needed
}
//至少要有一个工作线程
addWorker(null, false);
}
}
scss
final void tryTerminate() {
for (;;) {
int c = ctl.get();
//检查是否允许终止
if (
//运行状态
isRunning(c) ||
//TIDYING或TERMINATED
runStateAtLeast(c, TIDYING) ||
//SHUTDOWN状态,队列不为空
(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
return;
//工作线程不为0
if (workerCountOf(c) != 0) { // Eligible to terminate
//终端一个worker
interruptIdleWorkers(ONLY_ONE);
return;
}
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
//CAS设置状态为TIDYING
if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
try {
//终止
terminated();
} finally {
//设置状态为终止
ctl.set(ctlOf(TERMINATED, 0));
//唤醒其他等待终止的线程
termination.signalAll();
}
return;
}
} finally {
mainLock.unlock();
}
// else retry on failed CAS
}
}
任务提交分析(execute()方法)
scss
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
//工作线程数小于核心线程数,创建一个worker去执行任务
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
//线程是运行状态并且添加工作队列成功
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
//不是运行状态并且一处队列成功
if (! isRunning(recheck) && remove(command))
//执行拒绝策略
reject(command);
//工作线程为0,创建一个worker,至少有一个工作线程去任务队列里拿任务处理
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//添加一个worker执行任务
else if (!addWorker(command, false))
//失败执行拒绝策略
reject(command);
}
addWorker()
- int c = ctl.get()获原子类的值默认ctlOf(RUNNING, 0),workerCountOf(c) < corePoolSize工作线程小于核心线程数。
ctlOf(RUNNING, 0)
arduino
private static int ctlOf(int rs, int wc) { return rs | wc; }
rs是RUNNING入参二进制是11100000_00000000_00000000_00000000,wc入参是0, rs|wc 就是高三位的状态值 workerCountOf(c)
arduino
private static int workerCountOf(int c) { return c & CAPACITY; }
workerCountOf(c)方法的计算c & CAPACITY(c & 00011111_11111111_11111111_11111111),屏蔽掉高三位拿到低29位得到工作线程数
- addWorker(command, true)
java
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
int c = ctl.get();
// c & ~CAPACITY 获取状态值(高三位)
//~CAPACITY 先取反拿到高三位,再c&取反的值,获取状态值
int rs = runStateOf(c);
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
//工作线程数
int wc = workerCountOf(c);
//工作线程数大于等于最大容量或者是核心线程大于等于核心线程数,
//非核心线程大于等于最大线程数。
//满足条件退出
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
//CAS操作把工作线程数加一
//成功了结束双层循环
if (compareAndIncrementWorkerCount(c))
break retry;
//重新获取状态 因为这时候线程池可能不是处于RUNNING状态
c = ctl.get(); // Re-read ctl
//说明线程池不是处于正常状态,继续外层循环
if (runStateOf(c) != rs)
continue retry;
//否则继续内层循环
// else CAS failed due to workerCount change; retry inner loop
}
}
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
//构造worker
w = new Worker(firstTask);
//这里是由线程池构建的对象
final Thread t = w.thread;
if (t != null) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
//运行状态
int rs = runStateOf(ctl.get());
//运行状态校验
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
//校验通过
//添加到线程池中的工作集合中
workers.add(w);
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
//添加成功
if (workerAdded) {
//启动工作线程
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
拒绝策略
1. 默认拒绝策略介绍
RejectedExecutionHandler 默认有4个实现
- AbortPolicy 抛异常
typescript
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
- CallerRunsPolicy 线程池不是关闭状态,由调用任务的线程自己执行
scss
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
- DiscardOldestPolicy 丢弃最早的任务并继续由线程池执行
scss
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
//从队列头部删除一个任务,也就是最早的任务
e.getQueue().poll();
e.execute(r);
}
}
- DiscardPolicy 丢弃任务
typescript
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
//啥都不做
}
java
private static final RejectedExecutionHandler defaultHandler =
new AbortPolicy();
2. 拒绝策略扩展
默认提供的拒绝策略是抛异常
java
private static final RejectedExecutionHandler defaultHandler =
new AbortPolicy();
自定义拒绝策略是实现RejectedExecutionHandler 接口,在构建线程池的时候通过构造方法传参指定即可
线程池执行流程总结
- 工作线程数小于核心线程数,添加一个worker执行任务(这其中核心包括:若是第一任务直接执行,接下来循环从任务队列中拿任务去执行,直到任务队列空了);
- 否则添加到任务队列;
- 否则添加一个worker执行任务(主要包括:如果成功的话和第一步逻辑一样,区别在于这里判断的是线程数是否大于等于最大线程数),失败执行拒绝策略。