构造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
corePoolSize–线程池长期维持的线程数
maximumPoolSize–最大线程数
keepAliveTime–线程空闲时间,超过这个时间会被回收
workQueue–任务阻塞队列
threadFactory–生产线程工厂,使用默认即可
handler–拒绝策略
线程池结构
//高三位表示线程池状态,低29位表示线程数
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
//表示可接受新任务,且可执行队列中的任务;
private static final int RUNNING = 111 00000 00000000 00000000 00000000;
//表示不接受新任务,但可执行队列中的任务;
private static final int SHUTDOWN = 000 00000 00000000 00000000 00000000;
//表示不接受新任务,且不再执行队列中的任务,且中断正在执行的任务
private static final int STOP = 001 00000 00000000 00000000 00000000;
//所有任务已经中止,且工作线程数量为0,最后变迁到这个状态的线程将要执行terminated()钩子方法,只会有一个线程执行这个方法
private static final int TIDYING = 010 00000 00000000 00000000 00000000;
//中止状态,已经执行完terminated()钩子方法
private static final int TERMINATED = 011 00000 00000000 00000000 00000000;
private static int ctlOf(int rs, int wc) { return rs | wc; }
//控制核心线程数量内的线程 是否可以被回收。true 可以,false不可以。
private volatile boolean allowCoreThreadTimeOut;
//拒绝策略
private volatile RejectedExecutionHandler handler;
//当allowCoreThreadTimeOut == false 时,会维护核心线程数量内的线程存活,超出部分会被超时,allowCoreThreadTimeOut == true 核心数量内的线程 空闲时 也会被回收
private volatile long keepAliveTime;
//任务队列,当线程池中的线程达到核心线程数量时,再提交任务 就会直接提交到 workQueue
private final BlockingQueue<Runnable> workQueue;
//线程池全局锁,增加worker 减少 worker 时需要持有mainLock , 修改线程池运行状态时,也需要。
private final ReentrantLock mainLock = new ReentrantLock();
//线程池中真正存放 worker->thread 的地方。
private final HashSet<Worker> workers = new HashSet<Worker>();
线程池状态
线程池状态不可逆,没有修改线程池状态的方法,除非shutdown、shutdownNow
任务提交
submit和execute都可以提交任务,submit用于提交关心返回结果的任务,execute用于提交不关心返回结果的任务。
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
public void execute(Runnable command){}
线程增加
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
//当前线程数小于核心线程池数量,此次提交任务,直接创建一个新的worker
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
/*
执行到这里有两种情况
1.当前线程池数量已经达到corePoolSize
2.addWorker失败(要么线程池状态大于等于SHUTDOWN,要么刚好处于核心线程数-1,被其他线程抢先提交了)
*/
//当前线程池处于running状态,尝试将task放入到workQueue中,这里使用offer不阻塞
if (isRunning(c) && workQueue.offer(command)) {
//双重检查,万一状态被其它线程修改了
int recheck = ctl.get();
//线程池非运行中,尝试把刚才添加的任务移除,如果移除成功说明还没被执行,直接拒绝。移除失败说明已经被其他线程执行了
if (! isRunning(recheck) && remove(command))
reject(command);
//至少保证有1个线程去队列中取任务(corePoolSize=0可能出现这种情况)
else if (workerCountOf(recheck) == 0)
//为null时,表示添加1个线程直接去任务队列取任务执行
addWorker(null, false);
}
/*
执行到这里,有两种情况
1.offer失败。说明当前queue 满了,这个时候如果当前线程数量尚未达到maximumPoolSize的话,会创建新的worker直接执行command,假设当前线程数量达到maximumPoolSize的话,这里也会失败,走拒绝策略
2.当前线程池是非running状态。这个时候因为command != null addWorker一定是返回false
*/
else if (!addWorker(command, false))
reject(command);
}
private boolean addWorker(Runnable firstTask, boolean core) {
/**
以下4种情况,添加失败:
1.线程池状态为STOP、TIDYING、TERMINATED,返回false
2.线程池状态等于SHUTDOWN且任务非空,返回false
3.线程池状态等于SHUTDOWN,任务为空且任务队列也为空,返回false,只有这个代码才可能出现
if (workerCountOf(recheck) == 0)
//为null时,表示添加1个线程直接去任务队列取任务执行
addWorker(null, false);
4.超过了线程数限制(core=true采用核心线程数限制,core=false采用maximumPoolSize线程数限制),返回false
*/
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
//判断当前线程池是否允许添加线程
if (rs >= SHUTDOWN &&
(rs != SHUTDOWN ||
firstTask != null ||
workQueue.isEmpty()))
return false;
//内部自旋,获取创建线程令牌的过程
for (;;) {
int wc = workerCountOf(c);
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
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 {
w = new Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
final ReentrantLock mainLock = this.mainLock;
//获取主锁,保护临界区。因为下面会添加worker到集合中
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();
workers.add(w);
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
//启动worker,会执行worker的run方法
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
任务执行
Worker(Runnable firstTask) {
setState(-1); // AQS状态为-1,不允许中断(线程都还没启动)
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
public void run() {
runWorker(this);
}
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
//提交的第一个任务
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // AQS的state为0,允许线程被中断了
boolean completedAbruptly = true;
try {
//先执行提交的第1个任务,然后不断去队列中取任务
while (task != null || (task = getTask()) != null) {
//Worker继续AQS,就是为了利用不可重入特性,这里加锁是避免万一被shutdown了,shutdown里也会去获取AQS锁,如果获取不到说明worker还在干活,获取到说明线程空闲就可以中断了。
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
/*
1.线程池状态大于等于STOP,直接中断
2.线程池状态小于STOP,清空线程的中断标志,不中断
*/
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
//使用try finally,即使钩子执行异常,异常也会被吞没。
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);
}
}
private Runnable getTask() {
// 是否超时
boolean timedOut = false; // Did the last poll() time out?
// 自旋
for (; ; ) {
int c = ctl.get();
int rs = runStateOf(c);
//当前程池状态是SHUTDOWN的时候会把队列中的任务执行完直到队列为空
//线程池状态是STOP时,返回null,外层的runWorker会调用processWorkerExit来回收线程
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}
// 获取工作线程数量
int wc = workerCountOf(c);
// 是否允许超时,有两种情况:
// 1. 是允许核心线程数超时,这种就是说所有的线程都可能超时
// 2. 是工作线程数大于了核心数量,这种肯定是允许超时的
// 注意,非核心线程是一定允许超时的,这里的超时其实是指取任务超时
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
//获取任务超时
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
try {
// 真正取任务的地方
// 默认情况,只有当工作线程数量大于核心线程数量时,才会调用poll方法触发超时调用,否则阻塞获取。poll(timeout, unit)方法会在超时时返回null
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}
线程回收
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 += w.completedTasks;
//移除线程
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);
}
}
线程池关闭
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(SHUTDOWN);
interruptIdleWorkers();
onShutdown(); // hook for ScheduledThreadPoolExecutor
} finally {
mainLock.unlock();
}
tryTerminate();
}
public List<Runnable> shutdownNow() {
List<Runnable> tasks;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(STOP);
interruptWorkers();
tasks = drainQueue();
} finally {
mainLock.unlock();
}
tryTerminate();
return tasks;
}
/**
* Transitions to TERMINATED state if either (SHUTDOWN and pool
* and queue empty) or (STOP and pool empty). If otherwise
* eligible to terminate but workerCount is nonzero, interrupts an
* idle worker to ensure that shutdown signals propagate. This
* method must be called following any action that might make
* termination possible -- reducing worker count or removing tasks
* from the queue during shutdown. The method is non-private to
* allow access from ScheduledThreadPoolExecutor.
*/
final void tryTerminate() {
for (;;) {
int c = ctl.get();
if (isRunning(c) ||
runStateAtLeast(c, TIDYING) ||
(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
return;
//1.shutdown且任务队列没有任务了
//2.stop状态,尝试中断所有线程
if (workerCountOf(c) != 0) { // Eligible to terminate
interruptIdleWorkers(ONLY_ONE);
return;
}
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
try {
terminated();
} finally {
ctl.set(ctlOf(TERMINATED, 0));
termination.signalAll();
}
return;
}
} finally {
mainLock.unlock();
}
// else retry on failed CAS
}
}
核心线程预热
/**
* Starts all core threads, causing them to idly wait for work. This
* overrides the default policy of starting core threads only when
* new tasks are executed.
*
* @return the number of threads started
*/
public int prestartAllCoreThreads() {
int n = 0;
//阻塞等待队列的任务
while (addWorker(null, true))
++n;
return n;
}
/**
* Starts a core thread, causing it to idly wait for work. This
* overrides the default policy of starting core threads only when
* new tasks are executed. This method will return {@code false}
* if all core threads have already been started.
*
* @return {@code true} if a thread was started
*/
public boolean prestartCoreThread() {
return workerCountOf(ctl.get()) < corePoolSize &&
addWorker(null, true);
}