一、说明
线程池的生命周期
- 线程池的状态
runState
和工作线程数量workerCount
共同保存在 AtomicInteger
类型的控制变量 ctl
中 - ctl高三位保存运行状态(23=8>5),低29位保存工作线程的数量(229-1)
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;
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;
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; }
RUNNING
接收新的任务,并且可执行队列里的任务SHUTDOWN
停止接收新任务,但可执行队列里的任务STOP
可执行队列里的任务,不执行队列里的任务,中断正在执行的任务TIDYING
所有任务都已终止,线程数为0,当线程池变为TIDYING状态时,会执行钩子函数terminated(),钩子方法是指使用一个抽象类实现接口,
一个抽象类实现这个接口,需要的方法设置为abstract,其它设置为空方法TERMINATED
终止状态,表示线程池已关闭,已经执行完terminated()钩子方法
判断当前线程池运行状态
private static boolean runStateLessThan(int c, int s) {
return c < s;
}
private static boolean runStateAtLeast(int c, int s) {
return c >= s;
}
private static boolean isRunning(int c) {
return c < SHUTDOWN;
}
public boolean isShutdown() {
return ! isRunning(ctl.get());
}
public boolean isTerminating() {
int c = ctl.get();
return ! isRunning(c) && runStateLessThan(c, TERMINATED);
}
public boolean isTerminated() {
return runStateAtLeast(ctl.get(), TERMINATED);
}
运行状态转换关系
二、理解
RUNNING
接收新的任务,并且可执行队列里的任务
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
SHUTDOWN
shutdown()
方法将线程池状态转换为SHUTDOWN
,停止接收新任务,但可执行队列里的任务
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(SHUTDOWN);
interruptIdleWorkers();
onShutdown();
} finally {
mainLock.unlock();
}
tryTerminate();
}
private void checkShutdownAccess() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(shutdownPerm);
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers)
security.checkAccess(w.thread);
} finally {
mainLock.unlock();
}
}
}
private void advanceRunState(int targetState) {
for (;;) {
int c = ctl.get();
if (runStateAtLeast(c, targetState) ||\
ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
break;
}
}
private void interruptIdleWorkers() {
interruptIdleWorkers(false);
}
private void interruptIdleWorkers(boolean onlyOne) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers) {
Thread t = w.thread;
if (!t.isInterrupted() && w.tryLock()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
} finally {
w.unlock();
}
}
if (onlyOne)
break;
}
} finally {
mainLock.unlock();
}
}
STOP
shutdownNow()
方法将线程池状态转换为STOP
,同时中断所有线程,停止接收新任务,不执行队列里的任务,中断正在执行的任务
public List<Runnable> shutdownNow() {
List<Runnable> tasks;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(STOP);
interruptWorkers();
tasks = drainQueue();
} finally {
mainLock.unlock();
}
tryTerminate();
return tasks;
}
TIDYING
所有任务都已终止,线程数为0,线程池变为TIDYING
状态,会执行钩子函数terminated()
,钩子方法是指使用一个抽象类实现接口,一个抽象类实现这个接口,需要的方法设置为abstract
,其它设置为空方法
final void tryTerminate() {
for (;;) {
int c = ctl.get();
if (isRunning(c) ||
runStateAtLeast(c, TIDYING) ||
(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
return;
if (workerCountOf(c) != 0) {
interruptIdleWorkers(ONLY_ONE);
return;
}
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
try {
terminated();
} finally {
ctl.set(ctlOf(TERMINATED, 0));
termination.signalAll();
}
return;
}
} finally {
mainLock.unlock();
}
}
}
termination
实现 Condition
接口,用于实现线程阻塞和唤醒
private final ReentrantLock mainLock = new ReentrantLock();
private final Condition termination = mainLock.newCondition();
TERMINATED
执行完terminated()
钩子方法,线程池已终止,变为TERMINATED
状态
三、实现
使用ThreadPoolExecutor
自定义线程池
详见:Java多线程 ThreadPoolExecutor自定义线程池
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)