系列回顾
在上一篇只说了线程池的基本策略和一个案例,可以参考看看线程池原理剖析一
ThreadPoolExecutor
部分注释翻译
ctl是线程池的一个控制状态量(AtomicInteger),他打包了两个变量,一个是workerCount,另一个runState
1:The main pool control state, ctl, is an atomic integer packing two conceptual fields
1.1:workerCount, indicating the effective number of threads 工作线程数量
1.2:runState, indicating whether running, shutting down etc 线程池运行状态
为了把他们两打包成一个int,我们限制workerCount最大值为2^29-1
2:In order to pack them into one int, we limit workerCount to (2^29)-1
运行状态提供了几个生命周期控制的值如下
3:The runState provides the main lifecycle control, taking on values:
3.1:RUNNING: Accept new tasks and process queued tasks 允许接收新任务,处理队列中的任务
3.2:SHUTDOWN: Don't accept new tasks, but process queued tasks 不接收新任务但可以处理队列中的任务
3.3:STOP: Don't accept new tasks, don't process queued tasks 不接收新任务不处理队列中的任务
and interrupt in-progress tasks 中断正在进行的任务
3.4: TIDYING: All tasks have terminated, workerCount is zero,所有任务停止,workerCount =0
线程状态转到TIDYING 会回调terminated()方法
the thread transitioning to state TIDYING will run the terminated() hook method.
3.5:TERMINATED: terminated() has completed terminated()执行完成
4:线程池状态的转换
4.1 RUNNING -> SHUTDOWN
调用shutdown
On invocation of shutdown(), perhaps implicitly in finalize()
4.2 (RUNNING or SHUTDOWN) -> STOP
调用shutdownNow
On invocation of shutdownNow()
4.3 SHUTDOWN -> TIDYING
队列和池子都是空的
When both queue and pool are empty
4.4 STOP -> TIDYING
池子是空的
When pool is empty
4.5 TIDYING -> TERMINATED
terminated执行完成
When the terminated() hook method has completed
静态变量分析
//包装runState和workerCount的AtomicInteger
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
//Integer.SIZE - 3 = 29,为什么是29? 因为有5个状态量,两位表示不了,只能三位表示。
private static final int COUNT_BITS = Integer.SIZE - 3;
//000111..1111 总共29个1
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
// runState is stored in the high-order bits 高三位
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;
// Packing and unpacking ctl
//解包装成runState
private static int runStateOf(int c) { return c & ~CAPACITY; }
//解包装成workerCount
private static int workerCountOf(int c) { return c & CAPACITY; }
//包装成ctl
private static int ctlOf(int rs, int wc) { return rs | wc; }
先从5个状态量入手吧
RUNNING = -1 << COUNT_BITS; //-1左移29位
-1怎么表示?计算机是补码表示的,而负数的补码表示是正数源码取反+1
1:00…0001(31个0) 取反后111…110(31个1)
-1:11…111(32个1)
RUNNING = 11100…000(29个0)
SHUTDOWN = 00000…000(32个0)
STOP = 00100…000(29个0)
TIDYING = 01000…000(30个0)
TERMINATED = 01100…000(29个0)
高三位
RUNNING = 111
SHUTDOWN =000
STOP =001
TIDYING =010
TERMINATED =011
//解包装成workerCount
private static int workerCountOf(int c) { return c & CAPACITY; }
c=ctl.get()
00011…111(29个1) &c = 低29位 ,也就是workerCount
//解包装成runState
private static int runStateOf(int c) { return c & ~CAPACITY; }
11100…000(29个0)&c = 高三位 也就是runState
//包装成ctl
private static int ctlOf(int rs, int wc) { return rs | wc; }
runState|workerCount = 高三位|低29位 = 32位 = ctl
execute方法分析
/**
* 在未来某个时刻执行该任务,这个任务可能是新线程执行也可能是线程池已有的线程执行
* 如果一个任务不可以提交执行,有下述几个原因:
* executor已经被shutdown
* 容量到达阈值
*/
//这个方法的执行策略和我[线程池原理剖析一]里面提到的提交策略是一样的
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
//如果工作线程<corePoolSize 就开启新线程执行这个任务
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
//否则入队列等待调度
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//队列已满,尝试创建线程执行任务,失败后执行拒绝策略
else if (!addWorker(command, false))
reject(command);
}
addWorker方法分析
这个方法主要做两件事,其一是workCount++,其二是创建线程,线程包装的任务是Worker
/**
* 在当前线程池状态,给定的corePoolSize,maxPoolSize的限制下
* 检查一个新线程是否可以被创建,如果可以创建,
* 那么workerCount会相应改变并且会执行第一个任务
* 这个方法返回false的情况如下:
* pool is stopped
* eligible to shut down
* 线程工厂创建线程失败
*
* 如果线程工厂创建线程失败,可能是因为工厂返回null,也可能是异常
* 典型异常就是在Thread.start()时内存溢出
* 这种情况下我们要回滚做清理操作
* @param core true:corePoolSize as bound , else maxPoolSize as bound
* @return true if successful
*/
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);// 线程池状态
// 这里有5种情况会返回false,(SHUTDOWN 不接收新任务但可以处理队列中的任务)
//case1:rs = STOP
//case2:rs = TIDYING
//case3:rs = TERMINATED
//case4:rs = SHUTDOWN && firstTask != null
//case5:rs = SHUTDOWN && workQueue是空
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
int wc = workerCountOf(c);//工作线程的数量
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
if (compareAndIncrementWorkerCount(c))//cas尝试把workerCount加1
break retry;//跳出retry下面这个外层循环
c = ctl.get(); // Re-read ctl //cas失败
if (runStateOf(c) != rs)//如果线程池状态在这期间发生改变
continue retry;继续retry下面这个外层循环,去检查可不可以接受这个任务
//如果线程池状态在这期间没有发生改变,继续内层循环cas操作
}
}
//到这里了workerCount一定做了+1操作,但是线程还没有创建,下面就是创建线程 TODO
boolean workerStarted = false; //工作/活跃线程 启动标志
boolean workerAdded = false;//工作/活跃线程 添加到works(这是个set)标志
Worker w = null;
try {
//Worker extends AQS implements Runnable。是一个不可重入独占锁,包装了线程和任务。
w = new Worker(firstTask);
final Thread t = w.thread;//worker包装的线程
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());//线程池的状态
//SHUTDOWN态不允许接受新任务,但可以执行阻塞队列里的任务
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {//运行态或者(SHUTDOWN 态 且 任务==null)
//这个时候这个线程还没有启动,如果启动了,抛异常
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
workers.add(w);//set集合把worker添加进去,这个集合存储的是工作/活跃线程
//阻塞队列存储的是超过corePoolSize的任务
int s = workers.size();
if (s > largestPoolSize)//更新largestPoolSize
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
t.start();//启动线程,回调Worker类里的run方法
workerStarted = true;
}
}
} finally {
//如果进了if,可能是t==null||t.isAlive()||t.start()抛出oom
if (! workerStarted)
addWorkerFailed(w);//回滚处理
//上面这个方法主要干三件事如下
//works.remove(w)
//workCount--
//尝试终止线程池tryTerminate
//Doug Lea 要求在可能会终止线程池的操作上必须执行tryTerminate方法,例如上面的remove(w)和workCount--
}
return workerStarted;
}
runWorker方法
t.start会回调Worker类的run方法
public void run() {
runWorker(this);
}
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;//任务,可能为null
w.firstTask = null;
//Worker state初始为-1,调用tryRelease()方法,
//将state置为0, interruptIfStarted()中只有state>=0才允许调用中断
w.unlock(); // allow interrupts,
boolean completedAbruptly = true;//
try {
//只有task为null才会从阻塞队列中拿任务
while (task != null || (task = getTask()) != null) {
w.lock();
// If pool is stopping, ensure thread is interrupted;
// if not, ensure thread is not interrupted. This
// requires a recheck in second case to deal with
// shutdownNow race while clearing interrupt
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
beforeExecute(wt, task);
Throwable thrown = null;
try {
task.run();//回调我们自己的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();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}