这篇文章将为大家详细讲解有关Java中线程池的内部原理分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
先看一下ThreadPoolExecutor类的execute方法:
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
//获取clt,clt记录着线程池状态和运行线程数。
int c = ctl.get();
//运行线程数小于核心线程数时,创建线程放入线程池中,并且运行当前任务。
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
//创建线程失败,重新获取clt。
c = ctl.get();
}
//线程池是运行状态并且运行线程大于核心线程数时,把任务放入队列中。
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
//重新检查线程池不是运行状态时,
//把任务移除队列,并通过拒绝策略对该任务进行处理。
if (! isRunning(recheck) && remove(command))
reject(command);
//当前运行线程数为0时,创建线程加入线程池中。
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//运行线程大于核心线程数时并且队列已满时,
//创建线程放入线程池中,并且运行当前任务。
else if (!addWorker(command, false))
//运行线程大于最大线程数时,失败则拒绝该任务
reject(command);
}
在execute方法中,多次调用的addWorker方法,再看一下这个方法:
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
//获取clt,clt记录着线程池状态和运行线程数。
int c = ctl.get();
//获取线程池的运行状态。
int rs = runStateOf(c);
//线程池处于关闭状态,或者当前任务为null
//或者队列不为空,则直接返回失败。
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
//获取线程池中的线程数
int wc = workerCountOf(c);
//线程数超过CAPACITY,则返回false;
//这里的core是addWorker方法的第二个参数,
//如果为true则根据核心线程数进行比较,
//如果为false则根据最大线程数进行比较。
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
//尝试增加线程数,如果成功,则跳出第一个for循环
if (compareAndIncrementWorkerCount(c))
break retry;
//如果增加线程数失败,则重新获取ctl
c = ctl.get();
//如果当前的运行状态不等于rs,说明状态已被改变,
//返回第一个for循环继续执行
if (runStateOf(c) != rs)
continue retry;
}
}
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
//根据当前任务来创建Worker对象
w = new Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
//获得锁以后,重新检查线程池状态
int rs = runStateOf(ctl.get());
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive())
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;
}
关于“Java中线程池的内部原理分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。