ctl属性:其前三位是运行状态位,后29位是线程个数
注:增加work时有重入锁
主要步骤
- 获取当前线程池的状态,如果是STOP,TIDYING,TERMINATED状态的话,则会返回false,如果现在状态是SHUTDOWN,只有在要运行的任务为空且还有还有工作任务时才可以添加线程,其他shutdown时不允许创建线程(线程池的状态不符合直接返回)
- 通过自旋的方式,判断要添加的Worker是否是corePool,如果是的话,那么则判断当前的workerCount是否大于corePoolsize,否则则判断是否大于maximumPoolSize,如果满足的话,说明workerCount超出了线程池大小,直接返回false。如果小于的话,那么判断是否成功将WorkerCount通过CAS操作增加1,如果增加成功的话。则进行到第3步,否则则判断当前线程池的状态,如果现在获取到的状态与进入自旋的状态不一致的话,那么则通过
continue retry
重新进行状态的判断。(判断是线程个数不大于最大值,不大于最大线程数的话自旋通过cas增加线程数,cas成功进入3步,cas失败的话判断线程池状态发生改变1开始重新判断线程池状态,只是线程数发生变化的话内部循环自旋即可) - 如果满足了的话,那么则创建一个新的Worker对象,然后获取线程池的重入锁后,判断当前线程池的状态,如果当前线程池状态为STOP,TIDYING,TERMINATED的话,那么调用decrementWorkerCount将workerCount减一,然后调用tryTerminate停止线程池,并且返回false。(获取锁判断线程池的状态是运行中或者finlize中,是的话添加。添加成功后启动,失败后处理下失败)
注:ctl打包了运行状态runState和已被允许启动但不允许停止的工人数workerCount,高三位表示运行状态。双层for循环是因为最内层是需要cas,内层在cas失败,但是线程的运行状态没有改变只是work数量改变时继续cas即可,即最内层的循环。如果线程池的运行状态改变了,则需要重新读取线程池的运行状态。而外层是需要重新读取运行状态的。
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
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))
break retry;
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
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());
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
workers.add(w);
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}