首先分析内部类:ThreadPoolExecutor$Worker

//Worker对线程和任务做了一个封装,同时它又实现了Runnable接口,
//所以Worker类的线程跑的是自身的run方法
private final class Worker
extends AbstractQueuedSynchronizer implements Runnable
{
/** Thread this worker is running in. Null if factory fails. */
final Thread thread;
/** Initial task to run. Possibly null. */
Runnable firstTask;
/** Per-thread task counter */
volatile long completedTasks; /**
* Creates with given first task and thread from ThreadFactory.
* @param firstTask the first task (null if none)
*/
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
//创建一个Thread对象,它的Runnable对象是当前Worker对象
//创建了线程,但是还没启动,在外部start
//Executors.DefaultThreadFactory
this.thread = getThreadFactory().newThread(this);
} /** Delegates main run loop to outer runWorker */
public void run() {
runWorker(this);
} // Lock methods
//
// The value 0 represents the unlocked state.
// The value 1 represents the locked state. protected boolean isHeldExclusively() {
return getState() != 0;
} protected boolean tryAcquire(int unused) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
} protected boolean tryRelease(int unused) {
setExclusiveOwnerThread(null);
setState(0);
return true;
} public void lock() { acquire(1); }
public boolean tryLock() { return tryAcquire(1); }
public void unlock() { release(1); }
public boolean isLocked() { return isHeldExclusively(); } void interruptIfStarted() {
Thread t;
if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
}
}
}
} final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
//调用pool.execute()时传入任务时,如果addWorker返回为true,表示创建了worker,则任务也放在worker对象中了。
//如果addWorker返回为false,则把任务放入队列
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
//第二个task是从队列中取得的
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();
} 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);
}
} private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out? retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c); // Check if queue empty only if necessary.
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
} boolean timed; // Are workers subject to culling? for (;;) {
int wc = workerCountOf(c);
timed = allowCoreThreadTimeOut || wc > corePoolSize; if (wc <= maximumPoolSize && ! (timedOut && timed))
break;
if (compareAndDecrementWorkerCount(c))
return null;
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
} try {
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}

接着分析ThreadPoolExecutor

public class ThreadPoolExecutor extends AbstractExecutorService {
//状态变量,保存了workerCount和runState的值
//线程池的初始状态是RUNNING
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static int ctlOf(int rs, int wc) { return rs | wc; } //状态值从小到大排列
// 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; // 默认为 false,当线程池中已经有了 corePoolSize 个线程,即使这些线程不干活,也不会回收。
// 但是如果线程池中的线程数量超过了 corePoolSize,则会回收
private volatile boolean allowCoreThreadTimeOut; private volatile int corePoolSize; private volatile int maximumPoolSize; public void execute(Runnable command) {
if (command == null)
throw new NullPointerException(); int c = ctl.get();
//worker数量小于最小线程数,创建一个worker,并启动
//如果addWorker返回true,表示创建了一个worker对象,任务也放在worker对象中了。
//如果addWorker返回false,则随后把任务放入队列
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
//如果线程池处于运行状态,往队列投任务
//workQueue.offer(command)
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);
}
//如果workQueue.offer(command)返回false呢?
//当队列中积压的任务太多时,就会返回false
//这时传给addWorker的是false
else if (!addWorker(command, false))
reject(command);
} //core决定worker数量以corePoolSize和maximumPoolSize中哪一个值为上限
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 {
final ReentrantLock mainLock = this.mainLock;
w = new 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();
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;
} }

线程池接收任务的流程图:

关闭线程池有 shutdown 和 shutdownNow 2种方法:

shutdown 不再接收新任务,但会把队列中的任务执行完,shutdownNow 不会执行队列中的任务。

public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(SHUTDOWN);
interruptIdleWorkers();
onShutdown(); // hook for ScheduledThreadPoolExecutor
} finally {
mainLock.unlock();
}
tryTerminate();
} public List<Runnable> shutdownNow() {
List<Runnable> tasks;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(STOP);
interruptWorkers();
// 删除队列中的任务
tasks = drainQueue();
} finally {
mainLock.unlock();
}
tryTerminate();
return tasks;
}

shutdown 方法置线程池状态为 SHUTDOWN,shutdownNow 方法置为 STOP,线程池的线程一旦启动,会不停地从队列中取任务

getTask 的部分逻辑

int c = ctl.get();
// 获取线程池的状态
int rs = runStateOf(c); // Check if queue empty only if necessary.
// 状态如果为 SHUTDOWN,则当队列没有任务时,返回 null,即线程执行完 run 方法,执行结束;如果队列不空,则继续执行队列中的任务
// 状态如果为 STOP,则直接返回 null,不管队列是否有任务
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}

但是,shutdown 和 shutdownNow 一定会关闭线程池吗?这两个方法均是设置了状态,interrupt 了 worker,但是如果 worker 的 run 方法是一个死循环,而且它不关心这个 interrupt 标志位的话,那么线程是无法关闭的。当然正常的业务逻辑中,不会有这种情况。使用了 shutdown 后,因为这只是置标志,所以需要调用 awaitTermination 等线程池真正关闭或者超时。

假如一个 jvm 进程,有一个前台线程,多个 daemon 线程,当前台线程退出后,jvm 进程退出。

线程池创建线程时,daemon 属性默认为 false,即默认前台线程。

// java.util.concurrent.Executors.DefaultThreadFactory#newThread
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}

Thread 对象初始化时跟随当前线程的 daemon 属性


Thread parent = currentThread();

this.daemon = parent.isDaemon();

ThreadPoolExecutor类的更多相关文章

  1. eclipse在debug模式下总是自动进入到ThreadPoolExecutor类中

    当我们将web项目发布到tomcat服务器中,并且以debug模式启动的时候,总是自动跳转到 ThreadPoolExecutor 类中,如下: 解决办法 在eclipse中点击Window-> ...

  2. java线程池ThreadPoolExecutor类使用详解

    在<阿里巴巴java开发手册>中指出了线程资源必须通过线程池提供,不允许在应用中自行显示的创建线程,这样一方面是线程的创建更加规范,可以合理控制开辟线程的数量:另一方面线程的细节管理交给线 ...

  3. Java线程池ThreadPoolExecutor类源码分析

    前面我们在java线程池ThreadPoolExecutor类使用详解中对ThreadPoolExector线程池类的使用进行了详细阐述,这篇文章我们对其具体的源码进行一下分析和总结: 首先我们看下T ...

  4. 线程池 ThreadPoolExecutor 类的源码解析

    线程池 ThreadPoolExecutor 类的源码解析: 1:数据结构的分析: private final BlockingQueue<Runnable> workQueue;  // ...

  5. 高并发之——不得不说的线程池与ThreadPoolExecutor类浅析

    一.抛砖引玉 既然Java中支持以多线程的方式来执行相应的任务,但为什么在JDK1.5中又提供了线程池技术呢?这个问题大家自行脑补,多动脑,肯定没坏处,哈哈哈... 说起Java中的线程池技术,在很多 ...

  6. 并发系列(一)——线程池源码(ThreadPoolExecutor类)简析

    前言 本文主要是结合源码去线程池执行任务的过程,基于JDK 11,整个过程基本与JDK 8相同. 个人水平有限,文中若有表达有误的,欢迎大伙留言指出,谢谢了! 一.线程池简介 1.1 使用线程池的优点 ...

  7. 解析ThreadPoolExecutor类是如何保证线程池正确运行的

    摘要:对于线程池的核心类ThreadPoolExecutor来说,有哪些重要的属性和内部类为线程池的正确运行提供重要的保障呢? 本文分享自华为云社区<[高并发]通过源码深度解析ThreadPoo ...

  8. JUC多线程之ThreadPoolExecutor类任务执行流程

    ThreadPoolExecutor类: ThreadPoolExecutor是我们最常用的一个线程池类,它实现了AbstractExecutorService接口.首先来看一下它的构造器及相关关键变 ...

  9. 【高并发】不得不说的线程池与ThreadPoolExecutor类浅析

    大家好,我是冰河~~ 今天,我们一起来简单聊聊线程池中的ThreadPoolExecutor类,好了,不多说了,开始进入今天的正题. 一.抛砖引玉 既然Java中支持以多线程的方式来执行相应的任务,但 ...

  10. 【高并发】通过源码深度解析ThreadPoolExecutor类是如何保证线程池正确运行的

    大家好,我是冰河~~ 对于线程池的核心类ThreadPoolExecutor来说,有哪些重要的属性和内部类为线程池的正确运行提供重要的保障呢? ThreadPoolExecutor类中的重要属性 在T ...

随机推荐

  1. centos6.7rsync端与window2012服务器实时文件同步

    windows文件共享我就不截图了,估计大家都会,我就直接在centos6.7上操作了一.挂载win共享文件夹mount -t cifs -o username=administrator,passw ...

  2. Asterisk1.8 转码策略分析

    最近在修改asterisk转码和编码协商的问题,发现asterisk的转码策略的选择还是有些问题的(基于1.8.9.3版本).——————————————相关的CLI命令转码路径的调试命令:core ...

  3. Python3基础 input 输入浮点数,整数,字符串

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  4. redis安装使用配置

    一.安装前的准备 下载redis http://redis.io/download https://github.com/mythz/redis-windows 下载Windows版客户端net版sd ...

  5. 【附6】hystrix metrics and monitor

    一.基本方式 hystrix为每一个commandKey提供了计数器 二.实现流程 https://raw.githubusercontent.com/wiki/Netflix/Hystrix/ima ...

  6. 第十一章 非对称加密算法--DH

    注意:本节内容主要参考自<Java加密与解密的艺术(第2版)>第8章“高等加密算法--非对称加密算法” 11.1.非对称加密算法 特点: 发送方和接收方均有一个密钥对(公钥+私钥),其中公 ...

  7. 【转载】TCP 与 UDP 的区别

    原文地址:TCP 与 UDP 的区别 首先咱们弄清楚,TCP协议和UCP协议与TCP/IP协议的联系,很多人犯糊涂了,一直都是说TCP/IP协议与UDP协议的区别,我觉得这是没有从本质上弄清楚网络通信 ...

  8. POJ 1625 Censored!(AC自动机+高精度+dp)

    http://poj.org/problem?id=1625 题意: 给出一些单词,求长度为m的串不包含这些单词的个数. 思路: 这道题和HDU 2243和POJ 2778是一样的,不同的是这道题不取 ...

  9. LA 4329 乒乓比赛

    https://vjudge.net/problem/UVALive-4329 题意: 一条大街上住着n个兵乓球爱好者,经常组织比赛切磋技术.每个人都有一个不同的技能值ai.每场比赛需要3个人:两名选 ...

  10. POJ 1011 Sticks(dfs+剪枝)

    http://poj.org/problem?id=1011 题意:若干个相同长度的棍子被剪成若干长度的小棍,求每根棍子原来的可能最小长度. 思路:很经典的搜索题. 我一开始各种超时,这题需要很多剪枝 ...