JDK
版本:AdoptOpenJDK 11.0.10+9
参考:传送门
1 基本概念
ThreadPoolExecutor
是 j.u.c
提供的实现了 ExecutorService
接口的实现类,Executors
提供的很多线程池都是基于它来创建的。
ThreadPoolExecutor
并没有直接实现 ExecutorService
接口,而是继承了 AbstractExecutorService
抽象类,结构如下:
AbstractExecutorService
封装了线程池的一些通用逻辑,如果想自定义一个线程池,也可以通过继承这个抽象类来实现。
ThreadPoolExecutor
只是其中一种实现罢了:
public class ThreadPoolExecutor extends AbstractExecutorService {
......
}
2 ThreadPoolExecutor 基本元素
线程池的一般设计原理:
- 待执行的任务首先保存在任务队列中;
- 线程池分配一个空闲线程,从任务队列中取出一个待执行的任务,执行它;
- 线程池中没有空闲线程的时候,所有任务(包括新进来的任务)都将在任务队列中等待。
2.1 构造函数
一共有4
个构造函数,前三个都是由最后一个演化而来的:
// 第一个构造函数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
// 第二个构造函数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
// 第三个构造函数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
/**
* 第四个构造函数(重点)
* 使用给定的参数创建线程池
*
* @param corePoolSize 核心线程池允许创建的最大线程数
* @param maximumPoolSize 当任务队列满了,线程池允许创建的最大线程数
* @param keepAliveTime 空闲线程的存活时间
* @param unit keepAliveTime的单位
* @param workQueue 任务队列,保存已经提交但尚未被执行的任务
* @param threadFactory 线程工厂(用于指定如果创建一个线程)
* @param handler 拒绝策略(当任务太多导致工作队列满时的处理策略)
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
注意区分 corePoolSize
和 maximumPoolSize
:
corePoolSize
是指核心线程池中允许创建的最大工作线程的数量。当任务队列还没有满的时候,新来一个任务将会新建一个工作线程,直到达到corePoolSize
就不会再创建线程了,后边新来的任务将会在队列中排队。- 当任务队列满了,线程池可以继续创建新的工作线程来处理任务,直到工作线程的总数达到
maximumPoolSize
时就不再创建新的工作线程了。
2.2 线程池的状态
ThreadPoolExecutor
通过一个 AtomicInteger
类型的变量 ctl
来记录 线程池的状态 和 工作线程数。
低 29 位:工作线程数
高 3 位:线程池状态
// 状态变量ctl
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
// 最大线程数 2^29 - 1
private static final int COUNT_MASK = (1 << COUNT_BITS) - 1;
// 线程池5种状态
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;
一共定义了 5
种线程池状态:
- RUNNING:能够接收新任务,并且正在处理任务队列中的任务。
- SHUTDOWN:不接收新任务,但会去处理任务队列中已经存在的任务。
- STOP:不接收新任务,也不处理任务队列中已经存在的任务,同时中断正在执行的任务。
- TIDYING:当所有任务都已终止,工作线程数变为
0
,线程池会变为TIDYING
状态,并且会调用钩子函数terminated()
。 - TERMINATED:
terminated()
函数执行之后,,线程池会变为TERMINATED
状态。
如下图所示:
5个状态数值大小:RUNNING < SHUTDOWN < STOP < TIDYING < TERMINATED
2.3 Worker 工作线程
ThreadPoolExecutor
中通过内部类 Worker
来代表工作线程的,Worker
类继承 AQS
,实现了 Runnable
接口。
并且,通过一个 HashSet
来保存线程池中所有的工作线程。
// 工作线程的集合
private final HashSet<Worker> workers = new HashSet<>();
Worker
源码如下:
private final class Worker extends AbstractQueuedSynchronizer implements Runnable
{
// 序列化ID,虽然用不到
private static final long serialVersionUID = 6138294804551838833L;
// 关联的线程
final Thread thread;
//
Runnable firstTask;
//
volatile long completedTasks;
// 构造函数,工作线程的状态初始化为-1
Worker(Runnable firstTask) {
setState(-1);
this.firstTask = firstTask;
this.thread = getThreadFactory(</