这是我参与8月更文挑战的第16天,活动详情查看:8月更文挑战
线程池
好处/解决的问题
- 简而言之就是可复用,不用每次去new一个线程来执行,线程的创建和销毁都是非常消耗资源的
- 一种节制,因为线程池可以限制我们的线程个数,也可以动态新增
-其他它主要内部有一个成员变量
ctl是一个原子的Integer变量,来记录线程池状态和个数
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
类图如下
源码分析
execute
- execute是用来提交任务 command 到线程池进行执行。
- 判断如果任务为空,那么久抛出异常
- 获得当前线程池的状态
- 如果当前线程池中的线程个数小于
corePoolSize那么就要开启新线程运行 - 如果线程池处于
RUNNING,那么久添加任务到阻塞队列
private final BlockingQueue<Runnable> workQueue;
4.1 第二次检查
4.2 如果没有处于RUNNING状态,那么久从队列中删除任务,并且执行拒绝策略
4.3 最后都不满足,那么如果当前线程池为空,则添加一个线程
- 如果队列满了,那么就新增加线程,如果新增失败则执行拒绝策略
addWorker新增线程方法
6. 检查队列是否为空(只在必要时候)
- 循环CAS增加线程个数
7.1 如果线程数超过限制则false
7.2 CAS增加线程个数,并发条件只有一个线程成功
7.3 CAS失败,那么查看线程池状态是否变化,如果变化了,则调到外层循环重新尝试获取线程池的状态,否则内层循环重新CAS
- 循环过后,这里就是CAS已经成功 8.1 创建worker
8.2 加上独占锁,为了实现workers同步,因为可能有多个线程同时调用了线程池的excute的方法
8.3 重新检查线程池状态,避免在获得独占锁前调用shutdown接口