首先分析内部类: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. Django popup示例

    urls.py urlpatterns = [ url('popup_test1',views.popup_test1), url('popup_test2',views.popup_test2), ...

  2. 静态编译C/C++程序

    静态编译C/C++程序,让程序运行不受平台限制 由于Linux操作系统的特有elf加载顺序. (可以参考此文). 虽然可以很大程度上解决Windows早期版本的dll hell问题, 但是给部署带来了 ...

  3. oracle一些工作笔记

    表空间: oracle表空间对应的数据文件: SELECT t1.name, t2.name FROM v$tablespace t1, v$datafile t2 WHERE t1.ts#=t2.t ...

  4. 20145101《Java程序设计》第5周学习总结

    20145101<Java程序设计>第5周学习总结 教材学习内容总结 第八章 异常处理 Java是通过try,catch,throw,throws,finally这5个关键字来实现异常处理 ...

  5. Python3基础 issubclass 判断基类

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

  6. Android和PHP开发最佳实践

    Android和PHP开发最佳实践 <Android和PHP开发最佳实践>基本信息作者: 黄隽实丛书名: 移动应用开发技术丛书出版社:机械工业出版社ISBN:9787111410508上架 ...

  7. layer.alert自定义关闭回调事件

    在项目应用中,遇到自定义关闭layer.alert弹出层,即在关闭layer.alert时,可以自动触发关闭时的事件, 具体方法为: layer.alert('爱心提示!', function(){ ...

  8. NOI 16 买房子

    买房子(NOI 16) 总时间限制: 1000ms 内存限制: 65536kB 描述 某程序员开始工作,年薪N万,他希望在中关村公馆买一套60平米的房子,现在价格是200万,假设房子价格以每年百分之K ...

  9. 《剑指offer》第三_二题(不修改数组找出重复的数字)

    // 面试题3(二):不修改数组找出重复的数字 // 题目:在一个长度为n+1的数组里的所有数字都在1到n的范围内,所以数组中至 // 少有一个数字是重复的.请找出数组中任意一个重复的数字,但不能修改 ...

  10. cocos2dx 在windows下开启console

    cocos2dx 3.10 1.在main函数中写入代码 AllocConsole(); freopen("CONIN$", "r", stdin); freo ...