线程池 ThreadPoolExecutor 类的源码解析:

1:数据结构的分析:

private final BlockingQueue<Runnable> workQueue;  //用于存储未被线程池处理的任务

private final ReentrantLock mainLock = new ReentrantLock(); //维护一个lock来保证线程安全

private final HashSet<Worker> workers = new HashSet<Worker>();

private final Condition termination = mainLock.newCondition(); //通过Condition来进行线程之间的通信

private volatile ThreadFactory threadFactory;  //维护一个线程工厂,用于生成线程

private volatile RejectedExecutionHandler handler; //拒绝任务的句柄对象

private volatile int corePoolSize;  //核心池大小

private volatile int maximumPoolSize;  //最大池的大小

2:构造方法:将用户自定义的参数赋值给成员变量,并且使用默认的线程工厂,默认的任务拒绝

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue<Runnable> workQueue) {

this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,

Executors.defaultThreadFactory(), defaultHandler);

}

3:下面看看  execute 执行方法的原理:

public void execute(Runnable command) {

if (command == null)   //判空操作

throw new NullPointerException();

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);

}

下面主要分析下addWorker这个方法:

//以2种场景为例进行分析:

//1第一次添加任务到线程池中  2 第6次添加  corePoolsize=5

private boolean addWorker(Runnable firstTask, boolean core) { // firstTask就是Runnable任务 core=true

retry:

for (;;) {  //相当于while循环

int c = ctl.get(); //初始换后状态位Running  线程池中任务数为0

int rs = runStateOf(c); //获取线程池的状态 这里是RUNNING

// Check if queue empty only if necessary.

if (rs >= SHUTDOWN &&

! (rs == SHUTDOWN &&

firstTask == null &&

! workQueue.isEmpty()))

return false;

for (;;) { //相当于while循环

int wc = workerCountOf(c); //获取worker数量 wc=0

//判断线程池中线程是否超出了限制,若超出了则返回false

if (wc >= CAPACITY ||

wc >= (core ? corePoolSize : maximumPoolSize))

return false;

//CAS 将c的值+1  操作失败退出循环

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 {

//将传进来的Runnable 任务构建成Worker对象

w = new Worker(firstTask);

//获取worker对应的线程

final Thread t = w.thread;

if (t != null) {

//获取锁

final ReentrantLock mainLock = this.mainLock;

mainLock.lock();

try {

// Recheck while holding lock.

// Back out on ThreadFactory failure or if

// shut down before lock acquired.

int rs = runStateOf(ctl.get());//获取线程池状态 这里是RUNNING

//判断线程池状态

if (rs < SHUTDOWN ||

(rs == SHUTDOWN && firstTask == null)) {

if (t.isAlive()) // precheck that t is startable

throw new IllegalThreadStateException();

//将工作任务添加到workers集合中

workers.add(w);

int s = workers.size();

if (s > largestPoolSize)  //初始化时largestPoolSize=0

largestPoolSize = s; //赋值  largestPoolSize=1

workerAdded = true;  //这里true表明添加成功的标识,后面执行该线程

}

} finally {

mainLock.unlock();

}

if (workerAdded) {

t.start();  //线程开始执行

workerStarted = true;

}

}

} finally {

if (! workerStarted)

addWorkerFailed(w);

}

return workerStarted;

}

下面看看构建 Worker对象的逻辑:

Worker(Runnable firstTask) {

setState(-1); // 设置AQS state=-1

this.firstTask = firstTask; //任务赋值给firstTask全局变量

this.thread = getThreadFactory().newThread(this); //从线程工程创建新的线程

}

当第6次添加的时候

// command Runnable 任务

public void execute(Runnable command) {

if (command == null)

throw new NullPointerException();

int c = ctl.get();  //获取线程池的状态 这里是Running

if (workerCountOf(c) < corePoolSize) {  //这里c的任务数是5 corePoolSize=5

if (addWorker(command, true))

return;

c = ctl.get();

}

// 判断线程池的状态是不是Ruuning  将任务添加到队列中

if (isRunning(c) && workQueue.offer(command)) {//进入这个逻辑

int recheck = ctl.get(); //再次获取ctl对象

if (! isRunning(recheck) && remove(command)) //线程池状态不是Running 或者任务被移除则局拒绝任务

reject(command);

else if (workerCountOf(recheck) == 0)

addWorker(null, false); //添加空任务到worker中

}

else if (!addWorker(command, false))

reject(command);

}

到这里线程池的分析已经结束了;

线程池 ThreadPoolExecutor 类的源码解析的更多相关文章

  1. 线程池 ThreadPoolExecutor 原理及源码笔记

    前言 前面在学习 JUC 源码时,很多代码举例中都使用了线程池 ThreadPoolExecutor,并且在工作中也经常用到线程池,所以现在就一步一步看看,线程池的源码,了解其背后的核心原理. 公众号 ...

  2. Java 多线程(五)—— 线程池基础 之 FutureTask源码解析

    FutureTask是一个支持取消行为的异步任务执行器.该类实现了Future接口的方法. 如: 取消任务执行 查询任务是否执行完成 获取任务执行结果(”get“任务必须得执行完成才能获取结果,否则会 ...

  3. 并发编程(十二)—— Java 线程池 实现原理与源码深度解析 之 submit 方法 (二)

    在上一篇<并发编程(十一)—— Java 线程池 实现原理与源码深度解析(一)>中提到了线程池ThreadPoolExecutor的原理以及它的execute方法.这篇文章是接着上一篇文章 ...

  4. 【高并发】通过ThreadPoolExecutor类的源码深度解析线程池执行任务的核心流程

    核心逻辑概述 ThreadPoolExecutor是Java线程池中最核心的类之一,它能够保证线程池按照正常的业务逻辑执行任务,并通过原子方式更新线程池每个阶段的状态. ThreadPoolExecu ...

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

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

  6. Java并发指南12:深度解读 java 线程池设计思想及源码实现

    ​深度解读 java 线程池设计思想及源码实现 转自 https://javadoop.com/2017/09/05/java-thread-pool/hmsr=toutiao.io&utm_ ...

  7. 【转载】深度解读 java 线程池设计思想及源码实现

    总览 开篇来一些废话.下图是 java 线程池几个相关类的继承结构: 先简单说说这个继承结构,Executor 位于最顶层,也是最简单的,就一个 execute(Runnable runnable) ...

  8. 线程池ThreadPoolExecutor类的使用

    1.使用线程池的好处? 第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗. 第二:提高响应速度.当任务到达时,任务可以不需要等到线程创建就能立即执行. 第三:提高线程的可管理性 ...

  9. JDBC线程池创建与DBCP源码阅读

    创建数据库连接是一个比较消耗性能的操作,同时在并发量较大的情况下创建过多的连接对服务器形成巨大的压力.对于资源的频繁分配﹑释放所造成的问题,使用连接池技术是一种比较好的解决方式. 在Java中,连接池 ...

随机推荐

  1. 博文与文档发布玩法:Github + MWeb + 语雀 + Cnbolgs

    本文会说两个话题, 1,如何将 Github 上的文档(如:dotnet-campus/doraemon-pocket: 哆啦A梦的口袋 - 收集效率工具与站点)发布到语雀. 2,如何在本地使用 Ma ...

  2. ORM:对象关系映射

    一.简单操作 定义:面向对象和关系型数据库的一种映射,通过操作对象的方式操作数据 对应关系: 类对应数据表 对象对应数据行(记录) 属性对应字段 导入:from app01 import models ...

  3. SQLi-LABS Page-2 (Adv Injections) Less23-Less26

    Less-23 GET - Error based - strip comments http://10.10.202.112/sqli/Less-23?id=1' Warning: mysql_fe ...

  4. 高性能TcpServer(C#) - 6.代码下载

    高性能TcpServer(C#) - 1.网络通信协议 高性能TcpServer(C#) - 2.创建高性能Socket服务器SocketAsyncEventArgs的实现(IOCP) 高性能TcpS ...

  5. Transformer —— attention is all you need

    https://www.cnblogs.com/rucwxb/p/10277217.html Transformer -- attention is all you need Transformer模 ...

  6. Linux驱动开发常用调试工具---之内存读写工具devmem和devkmem【转】

    转自:https://blog.csdn.net/gatieme/article/details/50964903 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原 ...

  7. Jquery ajax 同步阻塞引起的UI线程阻塞的坑(loading图片显示不出来,layer.load延迟)

    今天想做一个点击地市用ajax重新获取数据刷新页面功能,因为ajax属于耗时操作,想在获取数据且加载页面时显示加载遮罩层,结果发现了ajax的好多坑. 例如如上栗子,我想点击按钮让遮罩层显示,ajax ...

  8. java执行hive命令或者脚本

    java执行脚本 import java.io.*; import java.text.DateFormat; import java.text.SimpleDateFormat; import ja ...

  9. plantUML 安装

    plantUML 安装 资源 http://www.graphviz.org/ https://graphviz.gitlab.io/_pages/Download/windows/graphviz- ...

  10. AI AND THE BOTTOM LINE: 15 EXAMPLES OF ARTIFICIAL INTELLIGENCE IN FINANCE

    https://builtin.com/artificial-intelligence/ai-finance-banking-applications-companies f there's one ...