ThreadPoolExecutor简介

  1. 并发包中提供的一个线程池服务

线程池的工作过程

  1. 线程池刚创建,里面没有线程.任务队列是作为参数传进来的.线程池不会立即执行任务.
  2. 调用execute()方法添加一个任务,线程池会做如下判断:
    • 如果正在运行的线程数量小于corePoolSize,马上创建线程运行这个任务
    • 如果正在运行的线程数量大于或等于corePoolSize,这个任务放入队列
    • 如果队列满了,且正在运行的线程数量小于maximumPoolSize,就要创建线程运行这个任务
    • 如果队列满了,而且正在运行的线程数量大于或等于maximumPoolSize,通过 handler所指定的策略来处理此任务
  3. 当一个线程完成任务时,会从队列取下一个任务来执行
  4. 当一个线程空闲时,超过keepAliveTime,线程池会判断,如果当前运行的线程数大于corePoolSize,这个线程会被停掉.

任务队列选择

  1. ArrayBlockingQueue
  2. LinkedBlockingQueue 没有大小限制

handler选择

  1. ThreadPoolExecutor.AbortPolicy() 抛出java.util.concurrent.RejectedExecutionException异常
  2. ThreadPoolExecutor.CallerRunsPolicy() 重试添加当前的任务,他会自动重复调用execute()方法
  3. ThreadPoolExecutor.DiscardOldestPolicy() 抛弃旧的任务
  4. ThreadPoolExecutor.DiscardPolicy() 抛弃当前的任务

源码分析

jdk1.7.0_71

构造

1
2
3
4
5
6
7
8
9
public ThreadPoolExecutor(
int corePoolSize,//线程池维护线程的最少数量
int maximumPoolSize,//线程池维护线程的最大数量
long keepAliveTime,//线程池维护线程所允许的空闲时间
TimeUnit unit,//线程池维护线程所允许的空闲时间的单位
BlockingQueue<Runnable> workQueue,//线程池所使用的缓冲队列
ThreadFactory threadFactory,//执行程序创建新线程时使用的工厂
RejectedExecutionHandler handler//线程池对拒绝任务的处理策略
){}

execute(Runnable command) 添加任务到线程池

1
2
3
4
5
6
public void execute(Runnable command) {
//command为空抛异常
//如果正在运行的线程数量小于corePoolSize,会立即addWorker(),创建新线程运行
//如果正在执行的数量大于等于corePoolSize,将任务放到阻塞队列.如果阻塞队列没有满并且是运行着的,直接放入阻塞队列.放入队列之后还要再做一次检查,如果线程池不在运行状态,把刚才的任务移除,调用reject方法,否则查看worker数量,若为0起一个新的worker去执行任务
//加入队列失败的话,会addWorker尝试一个新的worker去执行任务,新worker创建失败,调用reject方法
}

addWorker(Runnable firstTask, boolean core)

详细查看此文章

1
2
3
firstTask表示需要跑的任务。
boolean类型的core参数为true的话表示使用线程池的基本大小
为false使用线程池最大大小
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c); // 线程池当前状态

// 这个判断转换成 rs >= SHUTDOWN && (rs != SHUTDOWN || firstTask != null || workQueue.isEmpty)。
// 概括为3个条件:
// 1. 线程池不在RUNNING状态并且状态是STOP、TIDYING或TERMINATED中的任意一种状态
// 2. 线程池不在RUNNING状态,线程池接受了新的任务
// 3. 线程池不在RUNNING状态,阻塞队列为空。 满足这3个条件中的任意一个的话,拒绝执行任务
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;

for (;;) {
int wc = workerCountOf(c); // 线程池线程个数
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize)) // 如果线程池线程数量超过线程池最大容量或者线程数量超过了基本大小(core参数为true,core参数为false的话判断超过最大大小)
return false; // 超过直接返回false
if (compareAndIncrementWorkerCount(c)) // 没有超过各种大小的话,cas操作线程池线程数量+1,cas成功的话跳出循环
break retry;
c = ctl.get(); // 重新检查状态
if (runStateOf(c) != rs) // 如果状态改变了,重新循环操作
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
// 走到这一步说明cas操作成功了,线程池线程数量+1
boolean workerStarted = false; // 任务是否成功启动标识
boolean workerAdded = false; // 任务是否添加成功标识
Worker w = null;
try {
final ReentrantLock mainLock = this.mainLock; // 得到线程池的可重入锁
w = new Worker(firstTask); // 基于任务firstTask构造worker
final Thread t = w.thread; // 使用Worker的属性thread,这个thread是使用ThreadFactory构造出来的
if (t != null) { // ThreadFactory构造出的Thread有可能是null,做个判断
mainLock.lock(); // 锁住,防止并发
try {
// 在锁住之后再重新检测一下状态
int c = ctl.get();
int rs = runStateOf(c);

if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) { // 如果线程池在RUNNING状态或者线程池在SHUTDOWN状态并且任务是个null
if (t.isAlive()) // 判断线程是否还活着,也就是说线程已经启动并且还没死掉
throw new IllegalThreadStateException(); // 如果存在已经启动并且还没死的线程,抛出异常
workers.add(w); // worker添加到线程池的workers属性中,是个HashSet
int s = workers.size(); // 得到目前线程池中的线程个数
if (s > largestPoolSize) // 如果线程池中的线程个数超过了线程池中的最大线程数时,更新一下这个最大线程数
largestPoolSize = s;
workerAdded = true; // 标识一下任务已经添加成功
}
} finally {
mainLock.unlock(); // 解锁
}
if (workerAdded) { // 如果任务添加成功,运行任务,改变一下任务成功启动标识
t.start(); // 启动线程,这里的t是Worker中的thread属性,所以相当于就是调用了Worker的run方法
workerStarted = true;
}
}
} finally {
if (! workerStarted) // 如果任务启动失败,调用addWorkerFailed方法
addWorkerFailed(w);
}
return workerStarted;
}

参考

http://fulong258.blog.163.com/blog/static/17895044201082951820935

http://www.oschina.net/question/12_2656

http://coach.iteye.com/blog/855850

http://fangjian0423.github.io/2016/03/22/java-threadpool-analysis/

ThreadPoolExecutor简介的更多相关文章

  1. JUC线程池之 ThreadPoolExecutor简介

    ThreadPoolExecutor简介 ThreadPoolExecutor是线程池类.对于线程池,可以通俗的将它理解为"存放一定数量线程的一个线程集合.线程池允许若个线程同时允许,允许同 ...

  2. Java多线程系列——线程池原理之 ThreadPoolExecutor

    ThreadPoolExecutor 简介 ThreadPoolExecutor 是线程池类. 通俗的讲,它是一个存放一定数量线程的线程集合.线程池允许多个线程同时运行,同时运行的线程数量就是这个线程 ...

  3. Java - "JUC线程池" ThreadPoolExecutor原理解析

    Java多线程系列--“JUC线程池”02之 线程池原理(一) ThreadPoolExecutor简介 ThreadPoolExecutor是线程池类.对于线程池,可以通俗的将它理解为"存 ...

  4. J.U.C并发框架源码阅读(十三)ThreadPoolExecutor

    基于版本jdk1.7.0_80 java.util.concurrent.ThreadPoolExecutor 代码如下 /* * ORACLE PROPRIETARY/CONFIDENTIAL. U ...

  5. Java并发包--ThreadPoolExecutor

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509941.html ThreadPoolExecutor简介 ThreadPoolExecutor是线 ...

  6. Java线程池ThreadPoolExecutor极简教程

    ThreadPoolExecutor 简介 ThreadPoolExecutor 是 java.util.concurrent 包下的一个类,在jdk1.5版本引入,帮助开发人员管理线程并方便地执行并 ...

  7. java多线程系类:JUC线程池:02之线程池原理(一)

    在上一章"Java多线程系列--"JUC线程池"01之 线程池架构"中,我们了解了线程池的架构.线程池的实现类是ThreadPoolExecutor类.本章,我 ...

  8. Java多线程系列--“JUC线程池”02之 线程池原理(一)

    概要 在上一章"Java多线程系列--“JUC线程池”01之 线程池架构"中,我们了解了线程池的架构.线程池的实现类是ThreadPoolExecutor类.本章,我们通过分析Th ...

  9. KClient——kafka消息中间件源码解读

    目录 kclient消息中间件 kclient-processor top.ninwoo.kclient.app.KClientApplication top.ninwoo.kclient.app.K ...

随机推荐

  1. 熊猫猪新系统测试之三:iOS 8.0.2

    本来本猫要等到8.1版本出来后再做测试的,结果等来等去就是迟迟不推送更新呀!说好10月20号的iOS 8.1呢?为了一鼓作气写完,就先不等了.先拿手头的iOS 8.0.2系统做一下测试吧! 8.x系统 ...

  2. Xshell 链接 Could not connect to '192.168.80.129' (port 22): Connection failed

    在使用Xshell链接虚拟机VM里面的Linux的时候.链接失败,报 Could not connect to ): Connection failed 解决步骤: 1.重启VM.Linux.Xshe ...

  3. 解决记录:win10 无法安装VS2017,visual studio installer下载进度始终为0

    问题描述:win10 下无法安装VS2017,visual studio installer下载进度始终为0,点击取消按钮后,也没有反应,visual studio installer也关闭不掉: 具 ...

  4. Day19 Django

    老师代码博客: http://www.cnblogs.com/yuanchenqi/articles/7552333.html 上节内容回顾: class Book(models.Model): ti ...

  5. OAuth 2.0中文译本

    (一)背景知识 OAuth 2.0很可能是下一代的“用户验证和授权”标准,目前在国内还没有很靠谱的技术资料.为了弘扬“开放精神”,让业内的人更容易理解“开放平台”相关技术,进而长远地促进国内开放平台领 ...

  6. Python并发编程的几篇文章

    Python几种并发实现方案的性能比较 http://www.elias.cn/Python/PyConcurrency?from=Develop.PyConcurrency python并发编程 h ...

  7. Spring Boot @Async 异步任务执行

    1.任务执行和调度 Spring用TaskExecutor和TaskScheduler接口提供了异步执行和调度任务的抽象. Spring的TaskExecutor和java.util.concurre ...

  8. 大数据与Mapreduce

    第十五章 大数据与Maprudece 一.引言 实际生活中的数据量是非常庞大的,采用单机运行的方式可能需要若干天才能出结果,这显然不符合我们的预期,为了尽快的获得结果,我们将采用分布式的方式,将计算分 ...

  9. 115个Java面试题和答案——终极列表(上)【转】

    本文我们将要讨论Java面试中的各种不同类型的面试题,它们可以让雇主测试应聘者的Java和通用的面向对象编程的能力.下面的章节分为上下两篇,第一篇将要讨论面向对象编程和它的特点,关于Java和它的功能 ...

  10. javascript中字符串和字符串变量的问题

    var s = new String("hello"); s.indexOf(1) = 'p'; //错误,indexof()是函数 s[1]='p' //错误,在c和c++可以改 ...