简介
ThreadPoolExecutor
是Executor
接口的实现类,Executors
类的newFixedThreadPool
等方法创建的正是ThreadPoolExecutor
实例。
线程池流程
- 如果线程池当前线程数小于
corePoolSize
,则会创建新线程处理请求,即使当前有空闲线程; - 如果当前线程数大于等于
corePoolSize
,小于maximunPoolSize
,将当前请求放入阻塞队列,如果队列已满才会新建线程处理请求; - 如果线程数已经大于
maximunPoolSize
,则根据配置的拒绝策略进行处理。
Keep-Alive Time
如果线程池当前线程数大于corePoolSize
,此时空闲时间大于keepAliveTime
的线程将会被终止。默认情况下,keep-alive
策略仅仅针对线程数大于corePoolSize
的情况,通过allowCoreThreadTimeOut(boolean)
方法可以指定作用于core thread
。
队列类型
SynchronousQueue
SynchronousQueue
是一个不存储元素的阻塞队列,每一个put
操作必须等待一个take
操作,否则不能继续添加元素。
如果当前没有空闲线程可以立即处理请求,则入队失败,此时会创建一个新线程处理该请求,但是使用该队列一般需要配置无界的maximumPoolSizes
,避免可能交由拒绝策略进行处理的情况。
无界队列
例如没有指定大小的LinkedBlockingQueue
,使用无界队列时,如果当前所有的corePoolSize
线程正在处理请求时,新的请求过来就会进入阻塞队列中进行等待,因此线程池中最多只有coreSize
个线程,此时maximumPoolSize
没有任何影响。
此种队列适合每一个请求是相互独立的,请求执行时互不影响。例如在web page server
中,此种队列可以进行流量削峰。
有界队列
例如ArrayBlockingQueue
,在使用此种队列的情况下,通过指定有界的maximumPoolSizes
可以避免资源耗尽的情况。
拒绝策略
- AbortPolicy:默认策略,抛出RejectedExecutionException异常;
- CallerRunsPolicy:在调用
execute
的线程中运行任务; - DiscardPolicy:将任务丢弃;
- DiscardOldestPolicy:将队列头的任务丢弃。
钩子方法
通过重写beforeExecute(Thread, Runnable)
和afterExecute(Runnable, Throwable)
可以进行类似拦截器的操作。
数据结构
ThreadPoolExecutor 核心属性
ctl变量
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static int ctlOf(int rs, int wc) {
return rs | wc;
}
ctl
变量是线程池的控制状态,本身是一个原子整型,包含了两个核心概念:
- workerCount: 表示当前线程池有效的线程数量;
- runState: 表示线程池的状态,运行中、关闭等。
runState提供线程池生命周期的控制,具体如下:
- RUNNING: 可以接收新任务和处理队列中任务;
- SHUTDOWN: 不能接收新任务,但是会继续处理完队列中的任务;
- STOP: 不能接收新任务,无法处理队列中的任务,甚至中断运行中的任务;
- TIDYING: 所有任务已经结束,workCount为0,转换到状态TIDYING的线程将运行terminate钩子方法;
- TERMINATED: terminated方法执行结束。
生命周期状态转换如下:
- RUNNING -> SHUTDOWN : 调用了shutdown()方法;
- (RUNNING or SHUTDOWN) -> STOP : 调用了shutdownNow()方法;
- SHUTDOWN -> TIDYING : 队列和线程池都为空;
- STOP -> TIDYING: 线程池为空;
- TIDYING -> TERMINATED : 钩子方法terminated()执行完毕。因awaitTermination为阻塞的线程会返回,当线程池状态变为TERMINATED时。
生命周期状态源码如下:
private static final int COUNT_BITS = Integer.SIZE - 3; //29
private static final int CAPACITY = (1 << COUNT_BITS) - 1; //536870911
// runState is stored in the high-order bits
private static final int RUNNING = -1 << COUNT_BITS; //-536870912
private static final int SHUTDOWN = 0 << COUNT_BITS; //0
private static final int STOP = 1 << COUNT_BITS; //536870912
private static final int TIDYING = 2 << COUNT_BITS; //1073741824
private static final int TERMINATED = 3 << COUNT_BITS; //1610612736
//判断线程池是否运行状态
private static boolean isRunning(int c) {
return c < SHUTDOWN;
}
其他核心属性
//工作队列,即阻塞队列
private final BlockingQueue<Runnable> workQueue;
//互斥锁
private final ReentrantLock mainLock = new ReentrantLock();
//线程池中所有的工作线程
private final HashSet<Worker> workers = new HashSet<Worker>();
//支持awaitTermination的等待条件
private final Condition termination = mainLock.newCondition();
//
private int largestPoolSize;
//已结束任务的数量
private long completedTaskCount;
/**
* 所有由用户控制的参数都声明为volatile变量
*/
//创建线程的线程工厂
private volatile ThreadFactory threadFactory;
//拒绝策略处理器
private volatile RejectedExecutionHandler handler;
//等待任务的空闲线程的存活时间(纳秒级别)。默认情况下,只有线程数量超过corePoolSize时,该配置才会生效
private volatile long keepAliveTime;
//`core thread`是否会超时回收,默认为false
private volatile boolean allowCoreThreadTimeOut;
//默认情况下,线程池中的最小线程数量,当设置allowCoreThreadTimeOut时,最小数量为0
private volatile int corePoolSize;
//最大线程数量
private volatile int maximumPoolSize;
//默认拒绝策略为AbortPolicy
private static final RejectedExecutionHandler defaultHandler = new AbortPolicy();
Worker 核心属性
Worker类是ThreadPoolExecutor的内部类,继承了AQS,即是一个同步器,同时实现了Runnable接口。
final Thread thread;
//创建时的初始化任务,任务执行后置为空,后续Worker从阻塞队列中获取任务
Runnable firstTask;
//已完成任务数
volatile long completedTasks;
Worker方法详解
构造函数
Worker(Runnable firstTask) {
//设置共享变量
setState(-1);
this.firstTask = firstTask;
//新建线程
this.thread = getThreadFactory().newThread(this);
}
运行方法
public void run() {
//执行ThreadPoolExecutor的方法,稍后详解
runWorker(this);
}
同步器方法
isHeldExclusively()
//state为0表示无锁状态,为1表示锁住状态
protected boolean isHeldExclusively() {
return getState() != 0;
}
tryAcquire(int)
protected boolean tryAcquire(int unused) {
//使用CAS方法尝试加锁
//加锁成功设置当前线程为锁的持有者,并返回true
//加锁失败返回false
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
tryRelease(int)
protected boolean tryRelease(int unused) {
//将锁的持有者置为空,并将共享状态置为0
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) {
}
}
}
方法详解
一. 构造函数
ThreadPoolExecutor总共有4个构造函数,阿里规约推荐我们使用原生的构造函数创建线程池,而不是使用Executors工厂方法。
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);
}
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.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
二. 提交任务
我们通常会使用ThreadPoolExecutor
的submit(Runnable)
方法来提交任务,而该方法内部主要是通过execute(Runnable)
方法来实现。
execute(Runnable)
方法主要用来执行任务,任务可能通过新线程执行,也可能是线程池中现有空闲线程执行。
如果因为线程池shutdown
或者线程数已达上限,而导致任务无法执行,则该任务会交由RejectedExecutionHandler
处理。
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
//workerCountOf(c)方法获取到workerCount
//情况1: workerCount小于corePoolSize,则新增线程处理
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
//情况2: 当前线程池处于RUNNING状态,并且入队成功
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
//双重检查,如果此时线程池关闭并且出队成功,则交由RejectedExecutionHandler处理
if (!isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//情况3: 如果入队失败,则尝试新增线程处理,如果新增失败,则交由RejectedExecutionHandler处理
else if (!addWorker(command, false))
reject(command);
addWorker(Runnable, boolean)
addWorker方法主要完成如下工作:
- 新建Worker并加入workers集合中,并使用CAS为workCount加1;
- 启动Worker线程,执行runWorker方法;
- 如果添加Worker失败,将Worker从workers集合中移除,并将workCount减1
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
int c = ctl.get();
//获取runState
int rs = runStateOf(c);
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
//获取workerCount
int wc = workerCountOf(c);
//大于容量不创建新任务
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
//使用CAS方法增加workCount的数量
if (compareAndIncrementWorkerCount(c))
break retry;
c = ctl.get();
if (runStateOf(c) != rs)
continue retry;
}
}
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
//创建任务
w = new Worker(firstTask);
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());
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
//将任务加入到worker集合中
workers.add(w);
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
//启动线程,执行runWorker方法
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
runWorker(Worker)
Worker线程的run()
执行该方法,通过自旋处理firstTask或者阻塞队列里面的任务
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
// allow interrupts
w.unlock();
boolean completedAbruptly = true;
try {
//任务为空时,从阻塞队列中获取任务,循环直到队列为空
while (task != null || (task = getTask()) != null) {
// 如果拿到了任务,给自己上锁,表示当前Worker已经要开始执行任务了,已经不是闲置Worker
// getActiveCount返回正在执行的worker线程数量,正是通过worker的isLocked方法来判断
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 {
// 真正的开始执行任务,调用的是run方法,而不是start方法。这里run的时候可能会被中断,比如线程池调用了shutdownNow方法
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++;
// 执行完任务之后,解锁,Worker变成闲置Worker
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
ThreadPoolExecutor提交任务的大体流程如下:
- 如果workerCount小于corePoolSize,则新增worker线程处理,任务处理完毕后,后续worker线程从阻塞队列中获取任务执行;
- 如果workerCount大于等于corePoolSize,则将新任务加入阻塞队列中,如果加入失败(例如队列已满),则尝试新增线程处理,如果新增线程失败(例如线程数已大于等于maximumPoolSize),则交由拒绝策略处理器RejectedExecutionHandler处理。
- 执行完初始任务的worker线程会自旋获取阻塞队列中的任务。如果线程池当前线程数大于
corePoolSize
,此时空闲时间大于keepAliveTime
的线程将会被终止。默认情况下,keep-alive
策略仅仅针对线程数大于corePoolSize
的情况,通过allowCoreThreadTimeOut(boolean)
方法可以指定作用于core thread
。
三. 线程池关闭
(1) shutdown()
调用shutdown()
方法之后,线程池不会接受新的任务请求,但已有的任务会执行完毕。
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
//更新ctl变量,rs更新为SHUTDOWN状态,ws为现有worker线程数量
advanceRunState(SHUTDOWN);
interruptIdleWorkers();
onShutdown(); // hook for ScheduledThreadPoolExecutor
} finally {
mainLock.unlock();
}
tryTerminate();
}
tryTerminate()
final void tryTerminate() {
for (;;) {
//获取线程池状态
int c = ctl.get();
//当前线程池处于以下三种状态则返回:
//1.线程池还处于运行状态;
//2.线程池还处于TIDYING状态或TIDYING之前的状态
//3.线程池处于SHUTDOWN状态,但是工作队列还有任务,这也就意味着该方法会等待工作队列中的任务执行完毕
if (isRunning(c) ||
runStateAtLeast(c, TIDYING) ||
(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
return;
//进行线程中断
if (workerCountOf(c) != 0) { // Eligible to terminate
interruptIdleWorkers(ONLY_ONE);
return;
}
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
//更新tcl的rs为TIDYING,ws为0
if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
try {
//protected空方法,由子类实现自定义逻辑
terminated();
} finally {
//更新tcl的rs为TERMINATED
ctl.set(ctlOf(TERMINATED, 0));
termination.signalAll();
}
return;
}
} finally {
mainLock.unlock();
}
// else retry on failed CAS
}
}
(2) shutdownNow()
shutdownNow()会尝试停止所有正在执行的任务,暂停正在等待执行的任务的处理,并返回正在等待执行的任务的列表。
public List<Runnable> shutdownNow() {
List<Runnable> tasks;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
//直接将线程池状态更新为STOP,绕过了tryTerminate的判定校验
advanceRunState(STOP);
interruptWorkers();
tasks = drainQueue();
} finally {
mainLock.unlock();
}
tryTerminate();
return tasks;
}