线程池 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. 我脑中的JVM大全附带Java8的特性

    Java虚拟机-sun classic vm 世界上第一款商用的Java虚拟机. 只能使用纯解释器的方式来执行Java代码. Java虚拟机-ExactVM Exact Memory Manageme ...

  2. Linux命令: ps

    STAT 进程状态 S-睡眠 s-进程是会话向导进程 N拥有比普通优先级更低的 R-正在运行 D-短期等待 Z-僵尸进程 T被跟踪或者被停止 STATED 进程启动时间 TIME  进程使用CPU时间 ...

  3. 一不小心把windows资源管理器给结束任务了 电脑黑屏了 怎么处理

    按键盘上的三个键,Ctrl+Shift+Esc来启动任务管理器: 在任务管理器界面的左上角,有一个“文件”按钮,点击它会出现下拉的“新建任务(运行)...”按钮 鼠标点了“新建任务(运行)...”会弹 ...

  4. JSP 与Javabean 的交互技术

    JSP 与Javabean 的交互技术 JavaBean的属性可以是任意类型,并且一个JavaBean可以有多个属性.每个属性通常都需要具有相应的setter. getter方法,setter方法称为 ...

  5. 凯哥带你用python撸算法之雪花算法

    import time class Snow(object): def __init__(self, idx=None): init_date = time.strptime('2010-01-01 ...

  6. python_机器学习_监督学习模型_决策树

    决策树模型练习:https://www.kaggle.com/c/GiveMeSomeCredit/overview 1. 监督学习--分类 机器学习肿分类和预测算法的评估: a. 准确率 b.速度 ...

  7. istio部署-sidecar注入

    参考 fleeto/sleep fleeto/flaskapp 1. Sidecar注入 1.1 对工作负载的一些要求 支持的工作负载类型:Job,DaemonSet,ReplicaSet,Pod,D ...

  8. 4.Spark环境搭建和使用方法

    一.安装Spark spark和Hadoop可以部署在一起,相互协作,由Hadoop的HDFS.HBase等组件复制数据的存储和管理,由Spark负责数据的计算. Linux:CentOS Linux ...

  9. Rocketmq原理&最佳实践

    MQ背景&选型 消息队列作为高并发系统的核心组件之一,能够帮助业务系统解构提升开发效率和系统稳定性.主要具有以下优势: 削峰填谷(主要解决瞬时写压力大于应用服务能力导致消息丢失.系统奔溃等问题 ...

  10. E06 【买衣服】Maybe you need a bigger size

    核心句型 Maybe you need a bigger size 也许您需要大一些的. 场景对话 A:Can I try this jacket on,please? 我能试试这件夹克吗? B:Su ...