文章目录
线程池中的一些重要属性
//32-3=29
private static final int COUNT_BITS = Integer.SIZE - 3;
//线程池状态:运行中 这里是-1<<29==>1110 0000 0000 0000 0000 0000 0000 0000
private static final int RUNNING = -1 << COUNT_BITS;
///线程池状态:SHUTDOWN 0<<29==>0000 0000 0000 0000 0000 0000 0000 0000
private static final int SHUTDOWN = 0 << COUNT_BITS;
//线程池状态:STOP 1<<29==>0010 0000 0000 0000 0000 0000 0000 0000
private static final int STOP = 1 << COUNT_BITS;
//线程池状态:TIDYING 2<<29==>0100 0000 0000 0000 0000 0000 0000 0000
private static final int TIDYING = 2 << COUNT_BITS;
//线程池状态:TERMINATED 3<<29==>0110 0000 0000 0000 0000 0000 0000 0000
private static final int TERMINATED = 3 << COUNT_BITS;
//结合代码上下文看 表示的是线程数量的最大值
private static final int CAPACITY = (1 << COUNT_BITS) - 1
//结合上下文代码看 ctl值高3位表示线程池运行状态,低29位表示当前线程池拥有的线程数量
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
//工作队列
private final BlockingQueue<Runnable> workQueue;
//线程池中存放worker工作线程的地方
private final HashSet<Worker> workers = new HashSet<Worker>();
//线程池工厂 用来创建线程默认是DefaultThreadFactory
private volatile ThreadFactory threadFactory;
//拒绝策略 默认AbortPolicy
private volatile RejectedExecutionHandler handler;
//空闲线程存活时间
private volatile long keepAliveTime;
//控制核心线程数量是否可以被回收 true表示可以回收 false表示不可以回收
private volatile boolean allowCoreThreadTimeOut;
//核心线程数量
private volatile int corePoolSize;
//线程池最大线程数量
private volatile int maximumPoolSize;
通过计算发现,这几个线程池状态存在大小关系的:RUNNING<SHUTDOWN<STOP<TIDYING<TERMINATED
这里介绍下-1<<29、2<<29位的计算过程
-1<<29计算过程
- 计算-1的原码
-1的原码是1000 0000 0000 0000 0000 0000 0000 0001
-
计算-1的反码(原码除符号位外,按位取反)
1000 0000 0000 0000 0000 0000 0000 0001==>1111 1111 1111 1111 1111 1111 1111 1110
-
计算-1的补码(-1的反码+1)
1111 1111 1111 1111 1111 1111 1111 1110 + 0001==>1111 1111 1111 1111 1111 1111 1111 1111
-
-1的补码左移29位(每左移一位,低位补0)
1111 1111 1111 1111 1111 1111 1111 1111 << 29 ==>1110 0000 0000 0000 0000 0000 0000 0000
2<<29位的计算过程
-
计算2的原码
2的原码是0000 0000 0000 0000 0000 0000 0000 0010
-
2左移29位
0000 0000 0000 0000 0000 0000 0000 0010 << 29 ==>0100 0000 0000 0000 0000 0000 0000 0000
常见方法解析
runStateOf
//获取当前线程池运行状态
private static int runStateOf(int c) { return c & ~CAPACITY; }
假如入参c的二进制为1110 0000 0000 0000 0000 0000 0000 0011
~CAPACITY ==>~ 0001 1111 1111 1111 1111 1111 1111 1111 ==>1110 0000 0000 0000 0000 0000 0000 0000
1110 0000 0000 0000 0000 0000 0000 0011
1110 0000 0000 0000 0000 0000 0000 0000 ==> ~CAPACITY
----------------------------------------
1110 0000 0000 0000 0000 0000 0000 0000 ==> c & ~CAPACITY
workerCountOf
//获取当前线程池线程数量
private static int workerCountOf(int c) { return c & CAPACITY; }
假如入参c的二进制为1110 0000 0000 0000 0000 0000 0000 0011
1110 0000 0000 0000 0000 0000 0000 0011
0001 1111 1111 1111 1111 1111 1111 1111 ==> CAPACITY
----------------------------------------
0000 0000 0000 0000 0000 0000 0000 0011 ==> c & CAPACITY
最终结果0011==>3(十进制)
cltOf
主要用于重置当前线程池ctl值
//rs 线程池状态;wc 线程池线程数量
private static int ctlOf(int rs, int wc) { return rs | wc; }
以ctlOf(RUNNING,0)
为例进行计算
1110 0000 0000 0000 0000 0000 0000 0000 ==>rs
0000 0000 0000 0000 0000 0000 0000 0000 ==>wc 0
----------------------------------------
1110 0000 0000 0000 0000 0000 0000 0000 ==> 异或操作
线程池状态比较
runStateLessThan
private static boolean runStateLessThan(int c, int s) {
return c < s;
}
runStateAtLeast
private static boolean runStateAtLeast(int c, int s) {
return c >= s;
}
前面分析了 线程池状态有大小之别 因此可以进行比较,在这两个方法在后面比较常用
ThreadPoolExecutor构造函数
public ThreadPoolExecutor(int corePoolSize,// 核心线程数
int maximumPoolSize,// 最大线程数
long keepAliveTime,// 空闲线程存活时间
TimeUnit unit, //时间单位
BlockingQueue<Runnable> workQueue,//工作队列
ThreadFactory threadFactory, //线程工厂
RejectedExecutionHandler handler) {//拒绝策略
//合法性验证 这里主要 核心线程数要>=最大线程数
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
//对工作队列、线程工厂、拒绝策略进行验证
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
线程池工作单元Worker类解析
常用属性
//worker中封装的工作线程
final Thread thread;
//线程执行任务
Runnable firstTask;
//当前worker所完成任务数量
volatile long completedTasks;
常用方法解析
private final class Worker
extends AbstractQueuedSynchronizer
implements Runnable
首先看下Worker类的继承、实现关系。Worker继承了AQS,说明类中会加锁、解锁等操作,并且实现了Runnable接口,自然要有run方法去执行任务。
了解过AQS的都知道,AQS有两种模式:独占、共享。而这里使用的是独占模式,即必须等线程A释放锁后 线程B才能抢占到锁。
AQS中state表示同步状态 可以表示被抢占资源,当state=0时表示锁未被占用,state>0 表示被占用; state<0 表示初始状态 这种情况不能抢占锁
关于AQS内容 这里暂不深入 点到为止
lock
//Worker#lock
public void lock() { acquire(1); }
//AbstractQueuedSynchronizer#acquire
public final void acquire(int arg) {
//抢占锁成功 正常返回;抢占锁失败 将当前线程当做独占Node插入到等待队列
// 等待其他线程释放锁后唤醒它
//tryAcquire会被子类重写
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
protected boolean tryAcquire(int unused) {
//CAS成功 说明成功抢占锁
if (compareAndSetState(0, 1)) {
//将当前线程作为独占锁线程
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
unlock
//Worker#unlock
public void unlock() { release(1); }
//AbstractQueuedSynchronizer#release
public final boolean release(int arg) {
//如果资源释放完毕,则唤醒等待队列头结点;此时头节点的下一个等待节点会不断地自旋尝试获取锁
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
//Worker#tryRelease
protected boolean tryRelease(int unused) {
//独占线程置为null
setExclusiveOwnerThread(null);
//state置为0
setState(0);
return true;
}
run
public void run() {
//当工作线程启动后 就会执行这个方法去完成任务
runWorker(this);
}
execute
线程池提交任务的方式主要有两种: submit、execute
而submit
主要逻辑也是调用execute
,因此我们来看下execute实现的大体逻辑
因为execute方法中有调用到addWorker()
,为方便理解execute方法,这里先大致看下addWorker()
的实现
addWorker
//firstTask 线程执行的任务 可控
//core,true表示创建核心线程,false表示创建非核心线程
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
int c = ctl.get();
//获取线程池运行状态
int rs = runStateOf(c);
//rs>=SHUTDOWN有几种可能:SHUTDOWN STOP TIDYING TERMINATED
//! (rs == SHUTDOWN &&firstTask == null && ! workQueue.isEmpty()) 这个判断条件有些绕 我们整体理解下:当线程池状态不是运行中并且工作队列为空时 不允许再创建Worker;但是当工作队列不为空时即便线程池状态不是运行中 也运行创建worker,帮助处理工作队列的任务
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
//线程池工作线程数量
int wc = workerCountOf(c);
//如果工作线程数大于核心线程数或最大线程池数量 则无法添加Worker
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
// 走到这里 说明校验通过 可以创建worker 并将工作线程数量+1
if (compareAndIncrementWorkerCount(c))
//跳出retry循环
break retry;
//获取最新的ctl
c = ctl.get(); // Re-read ctl
// 这里线程池状态与rs不等,说明在addWorker期间 线程池状态发生过状态,比如调用过SHUTDOWN等
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
//worker是否启动成功
boolean workerStarted = false;
//worker是否添加成功
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());
//rs<SHUTDWON ==> 线程池运行状态为RUNNING 可以创建Worker
//rs == SHUTDOWN && firstTask == null 条件成立 说明此时创建的Worker是帮助处理工作队列任务的
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
//如果在启动线程前 发现线程已经存活
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
//将worker添加到HashSet中
workers.add(w);
int s = workers.size();
//如果线程池Worker数量> largestPoolSize,则更新largestPoolSize值
if (s > largestPoolSize)
largestPoolSize = s;
//Worker添加成功
workerAdded = true;
}
} finally {
//解锁
mainLock.unlock();
}
//如果worker添加成功则启动线程
if (workerAdded) {
t.start();
//线程启动成功标记
workerStarted = true;
}
}
} finally {
if (! workerStarted)
//处理worker添加失败的后续逻辑
addWorkerFailed(w);
}
return workerStarted;
}
该方法主要涉及以下逻辑:
1.检查线程池状态,判断是否再可以创建worker
2.检查线程池数量,判断是否再可以创建worker
3.创建worker
- 新建Worker对象 将其添加到HashSet,线程池数量+1
- 线程添加成功,即启动线程
- 线程启动成功,即正常退出 该方法响应true
- 线程启动失败,执行worker添加失败的逻辑
- 线程池数量-1
- 从线程池集合HashSet中移除该worker
- 清除线程池中的空闲线程
public void execute(Runnable command) {
//对任务进行非空判断
if (command == null)
throw new NullPointerException();
// 获取ctl 高三位 线程池状态;低29位 线程池数量
int c = ctl.get();
//如果线程池数量小于核心线程数
if (workerCountOf(c) < corePoolSize) {
//创建工作线程,并将command作为任务,创建成功即返回 ⭐️
if (addWorker(command, true))
return;
//程序走到这里,说明addWorker()失败了,失败原因大致有两种
//1.当前线程池数量已经超过核心线程数,不能再创建核心线程
//2.在创建核心线程时,外部有其他操作调用了线程池SHUTDOWN/SHUTDOWNNOW等 使此时线程池运行状态发生了改变
//获取最新的线程池ctl属性值
c = ctl.get();
}
//程序走到这里,有两种可能:
//1、线程池数量达到了核心线程数;2、addWorker()新建worker失败了
//isRunning(c) 成立 说明线程池状态为运行中,说明只是线程池数量达到了核心线程数
//workQueue.offer(command) 成立 说明 任务成功被添加到工作队列
if (isRunning(c) && workQueue.offer(command)) {
//获取最新的线程池ctl属性值
int recheck = ctl.get();
//! isRunning(recheck) 条件成立 说明线程池运行状态被改变了,可能外部调用了SHUTDOWN/SHUTDOWNNOW,因此需要将添加到工作队列的任务给删除
//remove(command) 如果删除成功,说明该任务提交到工作队列 还没有被线程处理
if (! isRunning(recheck) && remove(command))
//对任务执行拒绝策略
reject(command);
//如果线程池是运行状态 或者 任务删除失败的情况下 发现线程池线程数量为0
//这里会创建一个非核心线程
// 1.保障线程池在运行状态下 有线程在工作
// 2.非运行状态下 工作队列中的任务有线程能去执行
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//当线程池非运行状态 或者工作队列满时 程序会走到这里
//如果是工作队列满了,线程池会继续创建非核心线程数至maximumPoolSize,达到了maximumPoolSize后创建失败,会走到拒绝策略
//如果是非运行状态,线程池就不能再提交任务了,因此addWorker(command,false)也会失败,会走到拒绝策略
else if (!addWorker(command, false))
reject(command);
}
对execute()
方法的执行逻辑进行总结:
1、对提交上来的任务进行非空交易
2、当线程池线程数量小于核心线程数量时,创建核心线程
- 创建成功,程序执行结束
- 当线程池数量超过核心线程数或在创建核心线程时线程池变为非RUNNING状态,都会导致核心线程创建失败
3、当线程池数量超过核心线程数时,会将任务放到工作队列
- 当检测到线程池变为非RUNNING时,从工作队列删除添加的任务 并执行拒绝策略
- 线程池运行过程中发现线程数为0,则创建非核心线程 保障线程池中有线程在工作
4、当工作队列满时,尝试创建非核心线程
- 线程池线程数量达到maximumPoolSize,非核心线程创建失败,走拒绝策略
- 当线程池状态是SHUTDOWN/SHUTDOWNNOW时,不允许再提交任务 会走拒绝策略
runWorker()
前面的execute()
方法已经把任务提交到线程池了,这里我们看下任务是怎么执行的?
实际上,执行任务被封装在Worker
,而Worker
实现类Runnable接口,因此执行任务入口在run方法
//Worker#run
public void run() {
runWorker(this);
}
final void runWorker(Worker w) {
//获取当前线程
Thread wt = Thread.currentThread();
//获取待执行任务
Runnable task = w.firstTask;
w.firstTask = null;
//Worker构造函数 构造state=-1
//这里执行unlock 将独占线程置为null 将state由-1==>0 为w.lock()做准备
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
//这里Worker执行的任务有两个来源:1、线程池直接提交过来的 2、工作队列的
while (task != null || (task = getTask()) != null) {
//对worker加锁
w.lock();
// (runStateAtLeast(ctl.get(), STOP) 如果成立 说明线程池状态可能是STOP、TIDYING、TERMINATED
//Thread.interrupted() 获取线程中断状态 并重置中断标记位为false
//这个if块主要逻辑是 当线程池运行状态是STOP、TIDYING、TERMINATED 并且被中断了,那么要响应中断
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
// 这里需要注意 当worker取工作队列取不到任务被阻塞时,若worker响应中断了 会退出阻塞状态
wt.interrupt();
try {
//空方法 我们可以自己重写
beforeExecute(wt, task);
Throwable thrown = null;
try {
//这里就是调用Runnable#run方法了
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
task = null;
//完成任务数+1
w.completedTasks++;
//解锁
w.unlock();
}
}
//当没有任务要执行时,程序逻辑来到这里,紧接着就是执行Worker退出的逻辑;
//但是 当在执行任务过程中抛出了异常 则会执行执行到下面finally,
//所以 这个字段也可以标识 是否正常完成。false表示正常完成,true表示出异常了
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
总结一下这个方法的主要逻辑:
1、如果线程池提交任务为空或者工作队列任务为空 直接执行worker退出逻辑
2、若线程池状态为STOP、TIDYING、TERMINATED 并且Worker被中断了 则触发中断
3、正常执行任务
4、任务执行完毕,执行worker退出逻辑
processWorkerExit
当任务在执行完毕 会触发worker退出逻辑
//w 表示要退出的worker
//completedAbruptly true表示异常退出,false表示正常退出
private void processWorkerExit(Worker w, boolean completedAbruptly) {
//异常退出时,线程数-1
if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
decrementWorkerCount();
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
//如果是正常退出 更新完成任务数
completedTaskCount += w.completedTasks;
//从hashSet中移除该worker
workers.remove(w);
} finally {
mainLock.unlock();
}
//这个方法会清理空闲线程 并修改线程池状态,后面详细说
tryTerminate();
int c = ctl.get();
// runStateLessThan(c, STOP) 成立 说明当前线程池运行状态为RUNNING、SHUTDOWN
if (runStateLessThan(c, STOP)) {
//如果是正常退出
if (!completedAbruptly) {
//allowCoreThreadTimeOut 标识核心线程是否可回收,true标识超时可回收,false 则不可
// 这里是获取当前线程池最少拥有的线程数量
int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
// 当最少线程数为0 且工作队列不为空 那要给一个线程去执行工作队列任务
if (min == 0 && ! workQueue.isEmpty())
min = 1;
//当线程池线程数>最少线程池min时,说明线程池中还有线程 不需要额外创建线程
if (workerCountOf(c) >= min)
return; // replacement not needed
}
// 程序执行到这里 有两种前提条件:1、线程池中没有线程了 但是工作队列还有任务 因此要创建worker去执行
//2、触发processWorkerExit方法的worker是执行异常退出的,因此要再创建一个worker接着去执行任务
addWorker(null, false);
}
}
总结一下这个方法的主要逻辑:
1、如果worker是正常退出的
- 更新完成任务数,并从hashet中移除该worker
- 当线程池运行状态是RUNNING、SHUTDOWN,线程池线程数量为0 但是还有任务要执行时 则添加worker去执行
2、如果worker是异常退出的
- 线程池线程数量-1
- 新建一个worker 接着去执行任务
getTask
这里再来看一下从工作队列取任务的逻辑实现
private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out?
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// 条件成立有两种可能:1、rs >= SHUTDOWN && rs>=STOP ==>线程池已停止了
//2.rs >= SHUTDOWN && workQueue.isEmpty() 当前线程池状态为SHUTDOWN 并且工作队列为空
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
//线程池数量-1
decrementWorkerCount();
//取不到任务
return null;
}
//线程池线程数量
int wc = workerCountOf(c);
// 当允许核心线程被回收 或 线程池线程数大于核心线程数时 返回true
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
// (wc > maximumPoolSize || (timed && timedOut) 当线程池线程数量大于最大线程池数量 或 任务获取超时
//(wc > 1 || workQueue.isEmpty()) 线程池线程数量不为0 但是工作队列为空
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
//线程池线程数量-1
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
try {
//获取任务,根据timed属性值不同 获取任务时 可选支持超时机制或不支持超时机制
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
//任务获取超时
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}
该方法主要逻辑总结:
当worker获取执行任务时
- 如果线程池已停止或者工作队列为空 则不须再执行任务了,并将线程池线程数量减1
- 如果线程池线程数量大于最大线程数量 或者 获取任务超时 或者工作队列为空了,则不须再执行任务了,并将线程池线程数量减1
- 正常从工作队列取任务 并返回
shutdown
该方法会关闭线程池,将线程池运行状态置为SHUTDOWN。不再接受新的任务,会将以前提交的任务给执行了
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
//线程池运行状态置为SHUTDOWN
advanceRunState(SHUTDOWN);
//中断空闲线程
interruptIdleWorkers();
onShutdown(); // hook for ScheduledThreadPoolExecutor
} finally {
mainLock.unlock();
}
tryTerminate();
}
interruptIdleWorkers
private void interruptIdleWorkers(boolean onlyOne) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
//遍历worker集合
for (Worker w : workers) {
Thread t = w.thread;
//!t.isInterrupted() 成立的话 说明线程没有被中断
//w.tryLock() 成立的话 说明成功获取锁 也说明该worker没有执行runWorker方法 是空闲着的
if (!t.isInterrupted() && w.tryLock()) {
try {
//中断该线程
t.interrupt();
} catch (SecurityException ignore) {
} finally {
w.unlock();
}
}
//根据入参onlyOne的值 来决定是中断其中一个空闲worker,还是将全部空闲worker全部中断
if (onlyOne)
break;
}
} finally {
mainLock.unlock();
}
}
这里需要注意一下,work.thread 可能会在getTask()
方法,从工作队列取任务时被阻塞。如果worker已经是空闲状态,那么w.thread被中断,则work.thread
会从getTask()
取任务处被唤醒,最终因获取不到任务 而导致worker退出线程池。
tryTerminate
这个方法主要从事线程池终止的操作。
当线程池处于SHUTDOWN状态而且工作队列为空 或者 线程池处于STOP 状态并且线程池为空,那么线程池就可以终止了。如果在终止线程池时发现线程池线程数量不为0,则中断这些线程
final void tryTerminate() {
for (;;) {
//获取ctl
int c = ctl.get();
// isRunning(c) 如果线程池处于运行中 则退出终止操作
//runStateAtLeast(c, TIDYING) 如果条件成立 说明有其他线程在终止线程池,当前线程可以退出
//(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty() 如果还有任务没执行,则退出终止操作
if (isRunning(c) ||
runStateAtLeast(c, TIDYING) ||
(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
return;
//当决定要终止时,发现线程池线程数量不是0 则中断空闲线程,这里ONLY_ONE=true 即中断全部空闲线程
if (workerCountOf(c) != 0) { // Eligible to terminate
interruptIdleWorkers(ONLY_ONE);
return;
}
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// 将线程池运行状态设置为TIDING,与前面runStateAtLeast(c, TIDYING) 呼应上了
if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
try {
//空方法
terminated();
} finally {
//将线程池运行状态设置为TERMINATED
ctl.set(ctlOf(TERMINATED, 0));
//唤醒线程,纵观全局 应该是唤醒调用了awaitTermination方法的线程
termination.signalAll();
}
return;
}
} finally {
mainLock.unlock();
}
// else retry on failed CAS
}
}
对该方法进行总结:
1、若线程池处于运行状态 则线程池不进行终止
2、当线程池SHUTDOWN 但是工作队列有任务时,则线程池不进行终止
3、当有其他线程在终止线程池时,当前线程退出终止操作
4、终止线程池,将状态置为TERMINATED,并唤醒线程
shutdownNow
public List<Runnable> shutdownNow() {
List<Runnable> tasks;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
//线程池状态置为STOP
advanceRunState(STOP);
//中断所有线程
interruptWorkers();
//将工作队列中未执行的任务拿出来 返回出去
tasks = drainQueue();
} finally {
mainLock.unlock();
}
//在这里执行线程池终止操作
tryTerminate();
//返回未执行的任务
return tasks;
}
awaitTermination
调用了线程池的shutdown()与shutdownNow()方法之后,用户程序都不会主动等待线程池关闭完成,如果需要等待线程池关闭完成,需要调用awaitTermination()进行主动等待
public boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException {
long nanos = unit.toNanos(timeout);
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (;;) {
//线程池运行状态为TERMINATED
if (runStateAtLeast(ctl.get(), TERMINATED))
return true;
if (nanos <= 0)
return false;
//条件队列 在这里等待
//当线程池运行状态变为TERMINATED,会在tryTerminate 唤醒当前线程
nanos = termination.awaitNanos(nanos);
}
} finally {
mainLock.unlock();
}
}
如果线程池完成关闭,awaitTermination()方法将会返回true,否则当等待时间超过指定时间后将会返回false。如果线程池完成关闭,awaitTermination()方法将会返回true,否则当等待时间超过指定时间后将会返回false。
这里引用一段关闭线程池的代码
if(!threadPool.isTerminated()){
try{
for(int i=0;i<1000;i++){ //循环关闭1000次 每次等待10毫秒
if(threadPool.awaitTermination(10,TimeUnit.MILLISECONDS)){
break;
}
threadPool.shutdownNow();
}
}catch(InterruptedException e){
}catch(Throwable e){
}
}