属性
静态属性
COUNT_BITS=Integer.SIZE - 3=29;
CAPACITY =00011111111111111111111111111111;
RUNNING =11100000000000000000000000000000;
SHUTDOWN =00000000000000000000000000000000;
STOP =00100000000000000000000000000000;
TIDYING =01000000000000000000000000000000;
TERMINATED=01100000000000000000000000000000;
// 控制符,初始值为RUNNING
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
ctl=RUNNING=11100000000000000000000000000000;
// 包装与解包控制符:Packing and unpacking ctl
private static int runStateOf(int c) { return c & ~CAPACITY; }
private static int workerCountOf(int c) { return c & CAPACITY; }
private static int ctlOf(int rs, int wc) { return rs | wc; }
构造器参数,对应属性含义之前已经有介绍不再赘述:https://blog.csdn.net/u010597819/article/details/112758911
方法
ctlOf
根据线程池状态与线程数量生成ctl控制符,返回ctl值
应用
线程池进入下个运行状态
private void advanceRunState(int targetState) {
for (;;) {
int c = ctl.get();
// 1. 如果目标状态小于当前状态直接返回,即不允许回滚状态
if (runStateAtLeast(c, targetState) ||
// 2. 复制当前线程数,并重新按照目标状态生成新的ctl控制符,cas执行变更
ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
break;
}
}
workerCountOf
方法返回当前线程池线程数量
方法实现就是将ctl值与CAPACITY按位与运算,为什么这么计算也不多说,二者的二进制一看相信就没有疑问了,与运算可以理解为乘法运算,计算得出的正是当前任务数量。新增任务对ctl递增,完成任务则递减。
addWorker
添加任务并递增ctl
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
...
for (;;) {
// 判断线程数超出最大限制直接返回添加任务失败
int wc = workerCountOf(c);
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
// cas递增线程数
if (compareAndIncrementWorkerCount(c))
break retry;
...
}
private boolean compareAndIncrementWorkerCount(int expect) {
return ctl.compareAndSet(expect, expect + 1);
}
runWorker
完成任务递减ctl
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) {
w.lock();
...
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;
w.completedTasks++;
w.unlock();
}
}
// 任务等待队列已经没有值,正常完成作业的Worker
// 如果执行任务抛出异常,跳出方法,不会执行到该行代码,即为默认值:completedAbruptly = true;
completedAbruptly = false;
} finally {
// 完成作业的Worker执行退出逻辑
processWorkerExit(w, completedAbruptly);
}
}
processWorkerExit
退出Worker逻辑
private void processWorkerExit(Worker w, boolean completedAbruptly) {
// 1. 如果线程抛出异常,cas递减Worker
if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
// 1.1. 自旋方法,递减必须成功,否则自旋
decrementWorkerCount();
...
int c = ctl.get();
if (runStateLessThan(c, STOP)) {
// 2. 如果线程没有抛出异常则判断线程池水位
if (!completedAbruptly) {
int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
if (min == 0 && ! workQueue.isEmpty())
min = 1;
// 3. 如果线程数大于最小核心线程数,或者配置允许核心线程超时退出,
// 则退出当前核心线程Worker
if (workerCountOf(c) >= min)
return; // replacement not needed
}
// 4. 否则(即不满足条件3),添加非核心Worker等待工作,直至超时或新任务进来
addWorker(null, false);
}
}
runStateOf
方法返回当前线程池工作状态
运算符优先级复习一波
CAPACITY取反后的值等于RUNNING,与ctl按位与运算,得到结果必然等于某个状态值,RUNNING除了高3位是1之外均为0,也就是除了高三位之外的位与0按位与运算结果均为0。
getTask
从等待队列获取任务执行
private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out?
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// 如果当前线程池状态大于等于STOP,或者大于等于SHUTDOWN并且队列为空,
// 则递减ctl并退出Worker
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}
int wc = workerCountOf(c);
// Are workers subject to culling?
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
// (线程数超出最大限制,或者(允许核心线程超时或者线程数超出了核心线程限制)并且已超时),
// 并且,(线程数大于1,或者等待任务队列为空),则尝试递减ctl(非自旋)并退出当前Worker
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
// 尝试递减ctl(非自旋)并退出当前Worker
if (compareAndDecrementWorkerCount(c))
return null;
// 尝试递减失败重新开始循环
continue;
}
try {
// 等待新任务,如果允许超时则设置等待超时时间等待新任务,否则永久阻塞等待新任务
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
// 已超时,标志为已超时状态
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}
总结
- 使用位运算方式写代码可读性不高,好处是状态的判断以及数量的计算均通过位运算实现,性能高于常规算法写法
- ctl是32位Integer类型的控制符,首位是正负数标志位,高2-3位标志当前线程状态,低29位标志当前线程池线程数
退出Worker场景
- 用户线程正常完成,任务等待队列为空,并且允许核心线程超时并且已经超时,退出当前运行完成的Worker;任务等待队列不为空则保留一个Worker,如果线程池当前少于一个Worker则创建
- 用户线程抛出异常,并且允许核心线程超时并且已经超时,任务等待队列为空,退出当前运行完成的Worker;任务等待队列不为空则保留一个Worker,如果线程池当前少于一个Worker则创建
- 用户线程正常完成,任务等待队列为空,并且当前线程超出核心线程限制,退出当前运行完成的Worker
- 用户线程抛出异常,并且当前线程超出核心线程限制,退出当前运行完成的Worker
- 获取等待队列中的任务过程中判断当前线程池状态已经大于等于STOP状态,退出当前运行完成的Worker。注意此场景会忽略等待队列中的任务,即使有等待执行的任务也不会再启动线程作业。
- 获取等待队列中的任务过程中判断当前线程池状态已经等于SHUTDOWN状态,并且等待队列为空,执行步骤1,2,3,4的判断
退出Worker后立即生成新Worker场景
- 线程池状态小于STOP,用户线程抛出异常,创建新Worker
- 线程池状态小于STOP,用户线程正常完成,允许核心线程超时并且已经超时,如果任务等待队列不为空且线程池当前少于一个Worker则创建新Worker
- 线程池状态小于STOP,用户线程正常完成,不允许核心线程超时,如果当前线程池核心线程数小于配置的核心线程数则创建新Worker