java线程池(3)-线程池创建新线程的过程(原理)
前面的两期对于线程池的工作原理有了个大概的了解。那么线程池创建线程的过程是怎么样的呢?
首先,我们必须知道,线程池不会把我们传入的实现了Runable接口的类当做一个线程直接的启动。线程池会自己创建线程,然后去执行我们的所传入的任务的。会根据当前的线程池的状态和线程池中已有的线程池数量来决定是否创建一个新的线程来执行我们传入的任务。
我们,首先来看线程池创建线程的过程吧!
废话不多说,先上图。
线程池的主要流程可以分为以下几步:
- 获取线程池状态,线程池状态正确,执行2 线程池状态不正确返回false。
- 判断线程池中数目和传入的要求是否一致。不一致返回false,一致执行3
- CAS增加线程池的线程数(有个记录线程数的变量)。成功执行4,不成功执行1
- 获取线程池的锁,创建一个worker(也是线程)。
- 判断线程池的状态,状态正确。执行6,不正确返回false
- 将新添加的work放入存放线程的hashset中。启动线程成功!返回true,启动失败执行7
- 将刚才添加的线程从hashset中移除,然后返回false。
下面是代码和解释流程!
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
int c = ctl.get();
//获取线程池的状态,
int rs = runStateOf(c);
//按照不同的状态来区分执行,线程池状态值大于关闭也就不会接受新的任务了,如果线程池的状态不是运行态或者是
// 线程池是关闭态但是传入的Runable不是null或者任务队列不是null应该继续
// 也就是说线程池是关闭态但是任务队列中还有任务,或者有新的命令传入
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
//判断线程池中的线程个数。
int wc = workerCountOf(c);
//线程池中的线程数已超过了上限或者
// 是想作为核心线程池的线程但是线程池的核心线程池已经满了。
// 不作为核心线程池但是已经是最大的线程数目了。都返回false
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
//满足条件然后CAS的方式来增加线程池的线程数目标识
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;
ThreadPoolExecutor.Worker w = null;
try {
//创建一个线程,然后
final ReentrantLock mainLock = this.mainLock;
w = new ThreadPoolExecutor.Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
//获取线程池的共有锁
mainLock.lock();
try {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
int c = ctl.get();
int rs = runStateOf(c);
//
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
//新创建的线程池放入到hashset中
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;
}
主要看代码,图中解释的不是特别清楚,不过大概的流程还是可以看得明白的!这个就是线程池中产生新的线程的主要流程了!下一期主要说说线程池的关闭情况!希望大家可以多多支持,多提意见!