基本信息介绍
1.线程池是利用一个Integer也就是32位来保存线程池的基本信息,包括线程池状态,核心线程数量。
//当前核心线程数
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
//最大的核心线程数量 00011111 11111111 11111111 11111111
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
// runState is stored in the high-order bits
//运行状态 11100000 00000000 00000000 00000000
private static final int RUNNING = -1 << COUNT_BITS;
//结束状态 00000000 00000000 00000000 00000000
private static final int SHUTDOWN = 0 << COUNT_BITS;
//停止 00100000 00000000 00000000 00000000
private static final int STOP = 1 << COUNT_BITS;
// 01000000 00000000 00000000 00000000
private static final int TIDYING = 2 << COUNT_BITS;
// 01100000 00000000 00000000 00000000
private static final int TERMINATED = 3 << COUNT_BITS;
// Packing and unpacking ctl
/**
*RUNNING = 11100000 00000000 00000000 00000000
*CAPACITY = 00011111 11111111 11111111 11111111
* 一开始c(ctl)为: 11100000 00000000 00000000 00000000
* 增加一个核心线程之后: 11100000 00000000 00000000 00000001
*CAPACITY 取反 ~CAPACITY: 11100000 00000000 00000000 00000000
*所以runStateOf 为:
* c & ~CAPACITY=
* 11100000 00000000 00000000 00000000 (c)
* &
* 11100000 00000000 00000000 00000000 ( ~CAPACITY)
* =
* 11100000 00000000 00000000 00000000 = RUNNING
*/
private static int runStateOf(int c) { return c & ~CAPACITY; }
/**
*计算当前核心线程数的数量
* CAPACITY = 00011111 11111111 11111111 11111111
* RUNNING = 11100000 00000000 00000000 00000000
* int c = ctl.get();//当前核心线程数.一开始的时候
* ctl = ctlOf(RUNNING, 0);
* = RUNNING | 0
* = RUNNING
*
* 一开始c(ctl)为: 11100000 00000000 00000000 00000000
* 增加一个核心线程之后: 11100000 00000000 00000000 00000001
* 当前核心线程 workerCountOf(int c) { return c & CAPACITY; }
* 11100000 00000000 00000000 00000001
* &
* 00011111 11111111 11111111 11111111
* =
* 00000000 00000000 00000000 00000001
* 未计算简单流程
*/
private static int workerCountOf(int c) { return c & CAPACITY; }
private static int ctlOf(int rs, int wc) { return rs | wc; }
/**
* Timeout in nanoseconds for idle threads waiting for work.
* Threads use this timeout when there are more than corePoolSize
* present or if allowCoreThreadTimeOut. Otherwise they wait
* forever for new work.
* 这个时间是获取task的超时时间。
* 1.当线程池的线程数量不大于核心线程数的时候,
* 当allowCoreThreadTimeOut=false(默认为false)那么所有线程将一直等待任务不会超时(wait forever)。
* 当allowCoreThreadTimeOut=true的时候所有线程(包括核心线程数和超过非核心线程数的线程)都要按照超时时间(keepAliveTime)来获取任务。(也就是在keepAliveTime获取不到任务的话就回超时)
*2.当线程池的数量大于核心线程数的时候,所有线程(核心线程和非核心线程)都将按照超时时间(keepAliveTime)来获取任务。(也就是在keepAliveTime获取不到任务的话就回超时)
*/
private volatile long keepAliveTime;
/**
* Core pool size is the minimum number of workers to keep alive
* (and not allow to time out etc) unless allowCoreThreadTimeOut
* is set, in which case the minimum is zero.
* 扩展:其实核心线程和非核心线程没有本质的区别,这对于一些朋友可能会有一些误区。还有一点就是在RUNNING状态下的线程池,当没有任务可以获取的时候,最后剩下的线程的数量不一定就是corePoolSize的数量。可能的情况有:
* 1.正好与corePoolSize相等。(当allowCoreThreadTimeOut=false,任务数量不小于corePoolSize)
* 2.小于corePoolSize。(这种情况是当你的任务数量小于corePoolSize,eg:当你的corePoolSize为6,但是你只有3个task,那么最后线程池中剩余的线程数量就是3.)
* 3.为0。(这种情况下是设置了allowCoreThreadTimeOut=true)
*/
private volatile int corePoolSize;
/**
* If false (default), core threads stay alive even when idle.
* If true, core threads use keepAliveTime to time out waiting
* for work.
* 这个参数会让核心线程也按照keepAliveTime获取任务。
*/
private volatile boolean allowCoreThreadTimeOut;
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {//判断线程池状态
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
/**
*1、判断线程池当前是否为可以添加worker线程的状态,可以则继续下一步,不可以return false:
* A、线程池状态>shutdown,可能为stop、tidying、terminated,不能添加worker线程
* B、线程池状态==shutdown
* a.firstTask不为空,不能添加worker线程,因为shutdown状态的线程池
* 不接收新任务
* b.firstTask==null,workQueue为空,不能添加worker线程,因为
* firstTask为空是为了添加一个没有任务的线程再从workQueue获取task,而workQueue为
* 空,说明添加无任务线程已经没有意义
*/
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {//判断核心线程池数量
int wc = workerCountOf(c);
/**
* 1.如果大于线程池的最大容量(2^29 - 1)。直接false
* 2.如果创建的是核心线程,那么如果超出核心线程数的最大值:false。
* 如果创建的不是核心线程数,那么如果超出最大线程数:false
*
*/
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) {
/**
*这个锁可以控制worker增加
*/
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();
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从创建到启动的过程中出现了异常,那么要回滚之前的信息。
//1.从workers中移除加入的worker。(如果成功加入的话)
//2.当前线程的数量减一。
//3.tryTerminate
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
2.几个状态的转换。因为在线程池中状态的转换比较多,但是我们初次阅读源码的时候会因为看不懂状态和含义而苦恼,所以我在这里简单的总结一下。
其实线程的状态虽然有5种,但是我们可以大体上分为三种(RUNNING,Shuting Down,TERMINATED ),这也是ThreadPoolExector中toString()方法所描绘的。平时中我们关心的可能只有(RUNNING,TERMINATED ),而剩下的几个状态主要是线程池内部用到。
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
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;
1.RUNNING:最初的状态RUNNING来自于。
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
对象创建之初就是RUNNING。
2.SHUTDOWN:来自于shutdown();方法。这个状态下线程池不会再接收先任务,但是队列中原有的任务会继续执行完。
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(SHUTDOWN);
interruptIdleWorkers();
onShutdown(); // hook for ScheduledThreadPoolExecutor
} finally {
mainLock.unlock();
}
tryTerminate();
}
3.STOP:该状态来自于shutdownNow();方法。在这个状态下线程池不会再接收任务,并且队列中原有的任务也不会继续执行,并且尝试终止运行中的线程。
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;
}
4.TIDYING:来自于tryTerminate();
final void tryTerminate() {
for (;;) {
int c = ctl.get();
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 {
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
}
}
5.TERMINATED。当线程池不在RUNNING状态的时候,例如调用了shutdown(),shutdownNow(),线程池的最终状态就会进入TERMINATED。
final void tryTerminate() {
for (;;) {
int c = ctl.get();
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 {
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
}
}
线程池中的中断操作(tryTerminate();)只会中断从队列中获取任务的操作,而不会中断task的执行操作。
当线程池有负面增益的时候回调用tryTerminate()。那么主要都在哪些地方调用了呢?我在这里总结一下,当然也可以通过源码直接看到。
//添加线程失败
private void addWorkerFailed(Worker w){....}
//线程退出
private void processWorkerExit(Worker w, boolean completedAbruptly) {....}
//调用shutdown方法
public void shutdown() {...}
//调用shutdownNow
public List<Runnable> shutdownNow() {...}
//当线程池不是RUNNINT状态,并且新加入的任务没有被执行的时候
public boolean remove(Runnable task) {...}
/**
*以上就是线程池源码主要用到的地方。
*通过分析tryTerminate()源码我们可以总结出来:当线程池即将结束的时候,也就是不在是RUNNING,或者队列中没有任务的时候才会尝试终止线程池。
*这个时候线程池中的其他线程可能依旧在获取队列中的任务,不过都在那儿阻塞呢,这个时候这些线程就释放了worker上的锁,那么tryTerminate()这个方法的机会就来了,咔嚓一下子就给这些阻塞在上面的线程池中断了,这些被中断的线程只能重新再getTask中获取任务,但这时候这个被中断的线程再次通过getTask的时候已经发现队列为空了,就直接把线程池的线程数量减一,就把null返回了,然后runWork就执行到processWorkerExit()这里面会从workers中移除当前被中断的线程,这个时候总的线程数量就少一个了,这个时候processWorkerExit还回去看一下当前是线程池状态。
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);
}
若果是STOP那就不管了,线程数就回减一。如果是SHUTDOWN或者RUNNING就会去看看当前线程池最后允许剩下多少个线程,如果最后可以剩下0个那么min就是1,如果允许最后剩下corePoolSize那么min=corePoolSize,这个时候就要去看看线程池中到底还有没有线程了,如果还有,就看看剩下的多还是min多,如果剩下的多就不管了。等线程池中的其他线程执行到processWorkerExit就又会减一个线程。等最后一个线程执行到processWorkerExit这里之后还依旧要去看一下,到底是剩下的多还是min多,因为是最后一个线程了所以剩下的线程最大也不会超过min了,因为前边已经把它减一了。
*/
推荐:https://www.cnblogs.com/trust-freedom/p/6681948.html