ThreadPoolExecutor
一、概况
ThreadPoolExecutor是创建线程池对象,通过ThreadPoolExecutor可以创建线程池,但为什么不适用Executors创建呢,不是更简单吗,在《阿里巴巴java开发手册》里就建议使用ThreadPoolExecutor创建线程,而不是Executors;
原因:Executors创建线程池使用的队列都是无界队列,在设备内存有限的情况下,如果使用无限队列,会导致队列所存的数据大与设备内存,从而导致OOM,而使用ThreadPoolExecutor创建可以自定义队列,使用有界队列;
二、类图关系
三、四大构造函数
构造函数里都调用this.prestartAllCoreThreads();方法,这个方法是启动所有核心线程,返回启动的核心线程总数
该方法里调用addWorker()方法
addWorker()方法:他的主池控制状态ctl是一个原子整数包装两个概念字段 workerCount,指示有效线程数runState,指示是否运行,关闭等
也就是初始化线程池时会创建所有的核心线程,使用while循环调用addWorker方法,
- 线程初始化过程:
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
// 判断线程池状态
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
// 当线程池状态至少为SHUTDOWN,且以下三个条件任意一个为false时,则返回false,拒绝创建新的worker
// 1、rs == SHUTDOWN的false情况:线程池状态已经超过shutdown,可能是stop、tidying、terminated其中一个,即线程池已经终止
// 2、firstTask == null的false情况:firstTask不为空,场景是在线程池已经shutdown后,还要添加新的任务,拒绝
// 3、!workQueue.isEmpty()的false情况:workQueue为空,且rs >= SHUTDOWN,那么就没有添加新worker线程的必要了
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
int wc = workerCountOf(c);
// 这里判断线程数量是否超过边界,根据参数true or false来选择corePoolSize or maximumPoolSize,若超过边界,则拒绝任务
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
// 这里若成功将将线程数量+1,则跳出retry循环
if (compareAndIncrementWorkerCount(c))
break retry;
// 若没有成功将线程数量+1,则判断线程状态是否有改变,若改变了,则跳到外层循环重新执行之前的流程,若状态没有改变,则继续内层循环
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
// worker数量+1成功的后续操作,添加到workers Set集合,并启动worker线程
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
// 1、设置worker这个AQS锁的同步状态state=-1
// 2、将firstTask设置给worker的成员变量firstTask
// 3、使用worker自身这个runnable,调用ThreadFactory创建一个线程,并设置给worker的成员变量thread
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());
// 如果线程池在RUNNING状态,或者线程池已经在SHUTDOWN状态且firstTask==null(可能是workQueue中仍有未执行完成的任务,创建没有初始任务的worker线程执行)
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
// 线程已经启动,抛非法线程状态异常
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
workers.add(w);
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
// 释放锁
mainLock.unlock();
}
if (workerAdded) {
// 启动线程
t.start();
workerStarted = true;
}
}
} finally {
// 若启动线程失败,将worker从workers中移除,worker数量-1,并尝试中断线程
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
- 线程回收机制:如果没设置allowCoreThreadTimeOut为false(默认),即使核心线程空闲也不会回收,只回收超出核心线程数的其他线程,而如果为true,则会和其他线程一样,当线程空闲后会按照keepAliveTime超时时间进行回收
在执行任务时,执行完毕后会在finally中调用processWorkerExit方法,该方法就是
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) {
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 {
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++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
processWorkerExit方法具体执行:
private void processWorkerExit(Worker w, boolean completedAbruptly) {
if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
decrementWorkerCount();
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
//completedTaskCount记录完成的任务数累加
completedTaskCount += w.completedTasks;
//从hashset中移除改线程
workers.remove(w);
} finally {
mainLock.unlock();
}
tryTerminate();
int c = ctl.get();
if (runStateLessThan(c, STOP)) {
if (!completedAbruptly) {
int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
if (min == 0 && ! workQueue.isEmpty())
min = 1;
if (workerCountOf(c) >= min)
return; // replacement not needed
}
addWorker(null, false);
}
}
线程池状态:
其中ctl这个AtomicInteger原子操作类的功能很强大,其高3位用于维护线程池运行状态,低29位维护线程池中线程数量。
1、RUNNING:-1<<COUNT_BITS,即高3位为111,低29位为0,该状态的线程池会接收新任务,也会处理在阻塞队列中等待处理的任务;
2、SHUTDOWN:0<<COUNT_BITS,即高3位为000,低29位为0,该状态的线程池不会再接收新任务,但还是会处理已经提交到阻塞队列中等待处理的任务;
3、STOP:1<<COUNT_BITS,即高3位为001,低29位为0,该状态的线程池不会再接收新任务,不会处理在阻塞队列中等待的任务,而且还会中断正在运行的任务;
4、TIDYING:2<<COUNT_BITS,即高3位为010,低29位为0,所有任务都被终止了,线程数量workerCount为0,为此状态时还将调用terminated()方法,terminated()方法由子类实现;
5、TERMINATED:3<<COUNT_BITS,即高3位为011,低29位为0,terminated()方法调用完成后变成此状态。
这些状态均由int型表示,大小关系为 RUNNING<SHUTDOWN<STOP<TIDYING<TERMINATED,这个顺序基本上也是遵循线程池从运行到终止这个过程。
runStateOf(int c)方法:c & 高3位为1,低29位为0的~CAPACITY,用于获取高3位保存的线程池状态。
workerCountOf(int c)方法:c & 高3位为0,低29位为1的CAPACITY,用于获取低29位的线程数量。
ctlOf(int rs, int wc)方法:参数rs表示runState,参数wc表示workerCount,即根据runState和workerCount打包合并成ctl。
四、七大参数
corePoolSize:核心线程数
maximumPoolSize:最大线程数
keepAliveTime:空闲时存活时间
unit:存活时间单位
workQueue:队列
threadFactory:线程工程
handler:拒绝策略
五、四大拒绝策略
策略1:
ThreadPoolExecutor.AbortPolicy(),中止策略,将抛出 RejectedExecutionException。默认的情况下就是这种策略;
/**
* A handler for rejected tasks that throws a
* {@code RejectedExecutionException}.
抛出{@code RejectedExecutionException}的拒绝任务处理程序
*/
public static class AbortPolicy implements RejectedExecutionHandler {
/**
* Creates an {@code AbortPolicy}.
*/
public AbortPolicy() { }
/**
* Always throws RejectedExecutionException.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
* @throws RejectedExecutionException always
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
策略2:
ThreadPoolExecutor.CallerRunsPolicy()
CallerRunsPolicy从字面意思是调用者执行策略,也就是有主线程执行该任务;
/**
* A handler for rejected tasks that runs the rejected task
* directly in the calling thread of the {@code execute} method,
* unless the executor has been shut down, in which case the task
* is discarded.
处理被拒绝任务的处理程序,直接在{@code execute}方法的调用线程中运行被拒绝任务,除非执行器已关闭,在这种情况下,任务被丢弃
*/
public static class CallerRunsPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code CallerRunsPolicy}.
*/
public CallerRunsPolicy() { }
/**
* Executes task r in the caller's thread, unless the executor
* has been shut down, in which case the task is discarded.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
}
策略3:
ThreadPoolExecutor.DiscardOldestPolicy()
处理被拒绝任务的处理程序,它丢弃最旧的未处理请求,然后重试{@code execute},除非执行器(主线程)被关闭,在这种情况下,该任务将被丢弃
/**
* A handler for rejected tasks that discards the oldest unhandled
* request and then retries {@code execute}, unless the executor
* is shut down, in which case the task is discarded.
处理被拒绝任务的处理程序,它丢弃最旧的未处理请求,然后重试{@code execute},除非执行器(主线程)被关闭,在这种情况下,该任务将被丢弃。
*/
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardOldestPolicy} for the given executor.
*/
public DiscardOldestPolicy() { }
/**
* Obtains and ignores the next task that the executor
* would otherwise execute, if one is immediately available,
* and then retries execution of task r, unless the executor
* is shut down, in which case task r is instead discarded.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
e.getQueue().poll();
e.execute(r);
}
}
}
策略4:
ThreadPoolExecutor.DiscardPolicy
丢弃策略。无法执行的任务将被简单地删除,与策略1不同,不抛出异常。
/**
* A handler for rejected tasks that silently discards the
* rejected task.
*拒绝任务的处理程序,静默丢弃拒绝任务(即系不抛出异常)
*/
public static class DiscardPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardPolicy}.
*/
public DiscardPolicy() { }
/**
* Does nothing, which has the effect of discarding task r.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
}