当前位置:网站首页>线程池的执行流程
线程池的执行流程
2022-06-24 09:43:00 【文丑颜不良啊】

如果所示,就是线程池的执行过程,可以分为三个主要步骤:
1.提交任务后会首先进行当前工作线程数与核心线程数的比较,如果当前工作线程数小于核心线程数,则直接调用 addWorker() 方法创建一个核心线程去执行任务;
2.如果工作线程数大于核心线程数,即线程池核心线程数已满,则新任务会被添加到阻塞队列中等待执行,当然,添加队列之前也会进行队列是否为空的判断;
3.如果线程池里面存活的线程数已经等于核心线程数了,且阻塞队列已经满了,再会去判断当前线程数是否已经达到最大线程数 maximumPoolSize,如果没有达到,则会调用 addWorker() 方法创建一个非核心线程去执行任务;
4.如果当前线程的数量已经达到了最大线程数时,当有新的任务提交过来时,会执行拒绝策略
总结来说就是优先核心线程、阻塞队列次之,最后非核心线程。
java.util.concurrent.ThreadPoolExecutor#execute 的源码为:
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
/*
* Proceed in 3 steps:
*
* 1. If fewer than corePoolSize threads are running, try to
* start a new thread with the given command as its first
* task. The call to addWorker atomically checks runState and
* workerCount, and so prevents false alarms that would add
* threads when it shouldn't, by returning false.
*
* 2. If a task can be successfully queued, then we still need
* to double-check whether we should have added a thread
* (because existing ones died since last checking) or that
* the pool shut down since entry into this method. So we
* recheck state and if necessary roll back the enqueuing if
* stopped, or start a new thread if there are none.
*
* 3. If we cannot queue task, then we try to add a new
* thread. If it fails, we know we are shut down or saturated
* and so reject the task.
*/
int c = ctl.get();
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);
}可以看到,源码中的注释部分也说明了整个 excute() 方法的执行过程可分为三个步骤。
源码中变量 ctl 是一个原子类,主要作用是用来保存线程数量和线程池的状态。这里采用高 3 位来保存运行状态,低 29 位来保存线程数量。
在这几个步骤中,最重要的当属 addWorker() 方法了。
private boolean addWorker(Runnable firstTask, boolean core);第一个参数表示要执行的任务,如果为 null,则从阻塞队列中拉取任务;
第二个参数表示是否是核心线程,用来控制 addWorker() 的流程。
addWorker() 方法的实现主流程为:

源码为:
private boolean addWorker(Runnable firstTas
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if nec
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
int wc = workerCountOf(c);
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize
return false;
if (compareAndIncrementWorkerCo
break retry;
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to worke
}
}
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 =
mainLock.lock();
try {
// Recheck while holding lo
// Back out on ThreadFactor
// shut down before lock ac
int rs = runStateOf(ctl.get
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firs
if (t.isAlive()) // pre
throw new IllegalTh
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;
}addWorker() 执行过程中会反复使用 runStateOf() 和 workerCountOf() 来获取线程池的状态和工作线程的数量。
本文参考自:三分钟弄懂线程池执行过程 - 掘金
边栏推荐
- 被困英西中学的师生安全和食物有保障
- Geogebra instance clock
- CVPR 2022 oral | NVIDIA proposes an efficient visual transformer network a-vit with adaptive token. The calculation of unimportant tokens can be stopped in advance
- Troubleshooting steps for Oracle pool connection request timeout
- Honeypot 2 hfish, ehoney
- Arbre binaire partie 1
- Wechat cloud hosting launch public beta: in the appointment of the publicity meeting
- SQL sever试题求最晚入职日期
- CICFlowMeter源码分析以及为满足需求而进行的修改
- Juul, the American e-cigarette giant, suffered a disaster, and all products were forced off the shelves
猜你喜欢

415 binary tree (144. preorder traversal of binary tree, 145. postorder traversal of binary tree, 94. inorder traversal of binary tree)

uniapp 开发微信公众号,下拉框默认选中列表第一个

Cookie encryption 4 RPC method determines cookie encryption

Basic operations on binary tree

一群骷髅在飞canvas动画js特效

机器学习——感知机及K近邻

形状变化loader加载jsjs特效代码

二叉树第一部分

时尚的弹出模态登录注册窗口

Machine learning - principal component analysis (PCA)
随机推荐
GeoGebra 实例 时钟
二叉树第一部分
SQL sever试题求最晚入职日期
Network of test and development - Common Service Protocols
MySQL data advanced
oracle池式连接请求超时问题排查步骤
学习使用phpstripslashe函数去除反斜杠
微信小程序rich-text图片宽高自适应的方法介绍(rich-text富文本)
Cicflowmeter source code analysis and modification to meet requirements
有关二叉树 的基本操作
Jcim | AI based protein structure prediction in drug discovery: impacts and challenges
indexedDB本地存储,首页优化
Array seamless scrolling demo
Engine localization adaptation & Reconstruction notes
port 22: Connection refused
被困英西中学的师生安全和食物有保障
Programming questions (continuously updated)
Is there a reliable and low commission futures account opening channel in China? Is it safe to open an account online?
Error reading CSV (TSV) file
Queue queue