这是我参与8月更文挑战的第18天,活动详情查看:8月更文挑战
继续线程池源码系列
shutdown方法
- 检查权限
- 设置当前线程池的状态是
SHUTDOWN,如果已经是SHUTDOWN那么就直接返回 - 设置中断标志
- 尝试将状态改为
Terminate
- 其中3的操作如下
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();
}
}
- 以上代码是设置中断标志操作,在整个函数全局加锁
- 只创建了一个线程
t去调用interrupt设置中断标志 - 紧接着尝试获取
Worker自己的锁,获取成功则设置中断标志 - 如果已经获取了锁,那么就不会被中断 来看方法5
- 经过上面特判之后
- 开始尝试用
CAS将当前的线程设置为TIDYING状态 - 如果要是cas成功,则调用终止函数
- 将当前的线程池状态设为
TERMINATED - 将所有的
await的方法阻塞(使用的Condition)
shutdownNow操作
- 进行权限检查
- 将线程池状态设为
STOP - 中断所有线程
- 将队列任务移动到
tasks中
- 其主要做了,就是当执行
shutdownNow方法后 - 线程池就不会再接受新的任务了,而且会丢弃工作队列里面的任务
- 正在执行的任务也会被中断,并且不会等待激活的任务执行完成
awaitTermination
- 检验线程池的状态是否为
TERMINATED,全局采用了 独占锁
- 当线程调用了
TERMINATED方法后,当前线程就会被阻塞,然后死循环的方式去判断状态 - 代码中的
nanos是设置的超时时间,用来检验是否小于0,要是小于0就不需要等待直接返回 - 要是
nanos大于0,就调用awaitNanos进行赋值
总结
- 其实我们去查看线程池源码的时候,几乎每个方法里面都会有
ctl这个变量 - 这也是线程池之所以设计精妙的原因,只用一个原子变量来记录线程池的状态和线程池中的个数
- 进而通过线程池的状态来控制任务的执行
- 其中每个Worker线程还可以处理多个任务
池化的思想减少了线程创建与销毁带来的开销