一图胜千言:
源码
ctl共32位,其中前3位表示线程池的状态,0(000)、1(001)、2(010)、3(011)、-1(111)各表示一种,共五种,而后29位表示线程池中的线程个数
//其中AtomicInteger变量ctl的功能非常强大:利用低29位表示线程池中线程数,通过高3位表示线程池的运行状态:
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
//Integer的字节位数(32)- 3,所以COUNT_BITS的值为恒定值:29
private static final int COUNT_BITS = Integer.SIZE - 3;
//1的值左移29位,然后减1,很明显是29位为1的容量
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
// runState is stored in the high-order bits
//1、RUNNING:-1 << COUNT_BITS,即高3位为111,该状态的线程池会接收新任务,并处理阻塞队列中的任务;
private static final int RUNNING = -1 << COUNT_BITS;
//2、SHUTDOWN: 0 << COUNT_BITS,即高3位为000,该状态的线程池不会接收新任务,但会处理阻塞队列中的任务;
private static final int SHUTDOWN = 0 << COUNT_BITS;
//3、STOP : 1 << COUNT_BITS,即高3位为001,该状态的线程不会接收新任务,也不会处理阻塞队列中的任务,而且会中断正在运行的任务;
private static final int STOP = 1 << COUNT_BITS;
//4、TIDYING : 2 << COUNT_BITS,即高3位为010, 所有的任务都已经终止;
private static final int TIDYING = 2 << COUNT_BITS;
//5、TERMINATED: 3 << COUNT_BITS,即高3位为011, terminated()方法已经执行完成
private static final int TERMINATED = 3 << COUNT_BITS;
// Packing and unpacking ctl
//获取线程状态
private static int runStateOf(int c) { return c & ~CAPACITY; }
//获取线程池目前的线程数
private static int workerCountOf(int c) { return c & CAPACITY; }
private static int ctlOf(int rs, int wc) { return rs | wc; }
状态图:
ThreadPoolExecutor的execute方法:
/*
* Proceed in 3 steps:
//分 3 步进行:
*
* 1. If fewer than corePoolSize threads are running, try to
* start a new thread with the given command as its first
* task. The call to addWorker atomically checks runState and
* workerCount, and so prevents false alarms that would add
* threads when it shouldn't, by returning false.
// 1. 如果运行的线程少于 corePoolSize,尝试使用给定命令启动一个新线程作为其第一个任务。对 addWorker 的调用以原子方式检查 runState 和 workerCount,因此通过返回 false 来防止在不应该添加线程时添加线程的错误警报。
* 2. If a task can be successfully queued, then we still need
* to double-check whether we should have added a thread
* (because existing ones died since last checking) or that
* the pool shut down since entry into this method. So we
* recheck state and if necessary roll back the enqueuing if
* stopped, or start a new thread if there are none.
// 2. 如果一个任务可以成功排队,那么我们仍然需要仔细检查我们是否应该添加一个线程(因为现有的线程自上次检查后死亡)或者池在进入此方法后关闭。因此,我们重新检查状态,如果有必要,如果停止排队,则回滚,或者如果没有,则启动一个新线程。
* 3. If we cannot queue task, then we try to add a new
* thread. If it fails, we know we are shut down or saturated
* and so reject the task.
// 3.如果我们不能排队任务,那么我们尝试添加一个新线程。如果它失败了,我们知道我们已经关闭或饱和,因此拒绝任务。
*/
public void execute(Runnable command) {
//程序的健壮性,防止传进来的Runnable是个null值
if (command == null)
throw new NullPointerException();
//获取ctl标志:查看线程池状态,查看线程池中线程个数
int c = ctl.get();
//获取当前线程池中的线程数 与 核心线程数比较
if (workerCountOf(c) < corePoolSize) {
//如果当前线程未达到核心线程数,那么就添加核心线程,去执行任务
if (addWorker(command, true))
//添加成功,直接返回
return;
//如果没有添加上,那么就获取最新的ctl
//一般多线程同时执行execute操作时,假设线程1和线程2都在向同一个线程池提交任务,两者同时经过了判断,那么只能有一个添加成功,另一个就会来到此处
c = ctl.get();
}
//判断线程是否处于RUNNING状态,若处于,则提交给线程池中阻塞队列
if (isRunning(c) && workQueue.offer(command)) {
//再次获取ctl
int recheck = ctl.get();
//交给队列之后,再次获取当前线程执行状态看看是不是RUNNING,如果不是,那么要么处于shutdown状态,要么处于stop状态,这两个状态都不会接收新任务
if (!isRunning(recheck) && remove(command))
//如果移除了新任务,那么提交拒绝策略
reject(command);
//如果正在工作的线程数==0,但是此时队列中又有元素
else if (workerCountOf(recheck) == 0)
//那么添加一个新线程去执行任务,不能让队列干等
//三种情况:
//1.处于RUNNING状态那么addWorker就能布置添加任务
//2.如果处于SHUTDOWN状态,那么addWorker的任务参数必须不为null,若为null,则一定添加失败
//3.如果处于其他状态,那么直接添加失败
addWorker(null, false);
}
//此处的判断条件是:如果添加非核心线程都失败了,那么现在情况是:线程池处于RUNNING状态,核心线程数满了,队列也满了,并且最大线程数也创建满了
else if (!addWorker(command, false))
//那么直接提交拒绝策略
reject(command);
}
addWorker:
private boolean addWorker(Runnable firstTask, boolean core) {
//外层for循环退出的标志
retry:
for (;;) {
//获取当前ctl
int c = ctl.get();
//获取当前线程池状态
int rs = runStateOf(c);
// Check if queue empty only if necessary.
//本判断语句专门处理RUNNING以外的所有状态
//三种情况为true:
//1.状态不是RUNNING,且状态也不是SHUTDOWN
//2.状态是SHUTDOWN,但是传入的任务为null
//3.状态是SHUTDOWN,传入的任务不是null,但是阻塞队列是空的
//两种情况为false:
//1.状态是SHURDOWN,传入的任务是null,且队列中有元素
//2.状态时RUNNING
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN && firstTask == null && !workQueue.isEmpty()))
//SHUTDOWN状态:如果队列中有元素就继续处理,没有就终止
//STOP状态:队列中有元素也不处理
//TIDYING状态:由前两者过渡,彻底停止服务
//TERMINATED:Game Over
return false;
//开启内层for循环
for (;;) {
//获取当前正在工作的线程数
int wc = workerCountOf(c);
//判断为true的话有两种情况
//1.如果当前正在工作线程数大于最大线程计数
//2.1.如果只启用核心线程,但是wc超过核心线程数,那么为true
//2.2.如果启用了最大核心线程,但是wc超过了最大核心线程数,那么返回true
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
//若为true则添加线程失败
return false;
//CAS,将当前ctl做ctl++的原子操作。ctl后29位为计数为,此步开始添加线程
if (compareAndIncrementWorkerCount(c))
//退出外层死循环
break retry;
//CAS失败,那么更新ctl的值
c = ctl.get(); // Re-read ctl
//查看当前线程池状态是否改变了(原来是RUNNING)
if (runStateOf(c) != rs)
//如果改变为其他的了,那么又得去外层判断三种其他情况,否则还是RUNNING,若为RUNNING,那么自然满足外层循环条件,直接进内层循环
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);
// 从worker中获取线程t
final Thread t = w.thread;
//判断线程是否为null,一般都不是
if (t != null) {
//上锁
//加锁的目的:
//防止多线程条件下,当前线程使用时突然状态改变(此处没有自旋+CAS的判断,线程不安全)
//防止多线程造成的非原子性操作,导致工作线程同时入集合,造成的集合长度问题。
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状态且任务为空
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
//判断线程是否凉凉了,一般不会
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
//将worker添加到工作线程集合中
workers.add(w);
//工作线程集合长度+1
//此时获取工作线程集合长度
int s = workers.size();
//如果当前工作线程集合长度大于原本最大长度
if (s > largestPoolSize)
//那么更新集合最大长度
largestPoolSize = s;
//执行完后添加标志位改成true
workerAdded = true;
}
} finally {
//释放锁
mainLock.unlock();
}
if (workerAdded) {
//开启线程
t.start();
//线程开启标志位设置为true
workerStarted = true;
}
}
} finally {
//如果开启线程失败
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
Worker类:
worker类他实现了Runnable接口,此外还继承了AQS(AbstractQueuedSynchronizer)所以他既拥有run方法,还自带了AQS阻塞队列锁标记等一系列方法和标志位。
Worker的构造方法
Worker(Runnable firstTask) {
//设置AQS标志位为-1
//将标志位设置为-1,禁止中断直到 runWorker,runWorker方法在worker的run之中,也就是start调用后执行的方法。
setState(-1); // inhibit interrupts until runWorker
//将当前的任务设置为worker对象的属性
this.firstTask = firstTask;
//通过Factory创建线程,传入自身worker(自身也实现了Runnable,所以worker本质上也是个Runnable)
this.thread = getThreadFactory().newThread(this);
}
worker的构造方法中做了三件事,主要是设置标志位,将当前任务设置为自身属性,将自身传入工厂方法构造线程,并赋值给自身成员变量。
重写的run方法中只有一个runWorker方法,传入了自身
public void run() {
runWorker(this);
}
runWorker方法
final void runWorker(Worker w) {
//获取当前线程
Thread wt = Thread.currentThread();
//获取worker中的Runnable
Runnable task = w.firstTask;
//将worker中的Runnable置空
w.firstTask = null;
//将标志位设置为0
w.unlock(); // allow interrupts
//设置标记:是否因为异常退出循环
boolean completedAbruptly = true;
try {
//如果当前worker中有任务,或者worker中没任务,但是阻塞队列中有任务(getTask从阻塞队列中获取任务)
while (task != null || (task = getTask()) != null) {
//worker上锁,worker自己重写了lock方法,防止别的线程shutdown
w.lock();
// [如果运行的状态最小是STOP||(线程被打断&&线程运行状态最小为STOP)] && 当前线程没有被打断
// 如果线程池正在停止,那么要保证当前线程是中断状态;如果不是的话,则要保证当前线程不是中断状态
// 这里要考虑在执行该if语句期间可能也执行了shutdownNow方法,shutdownNow方法会把状态设置为STOP
if ( (runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP)) ) && !wt.isInterrupted() )
//那么打断线程
wt.interrupt();
try {
//执行任务前的方法
beforeExecute(wt, task);
Throwable thrown = null;
try {
//执行run方法
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;
//任务完成量+1
w.completedTasks++;
//解锁
w.unlock();
}
}
//是否因为异常退出循环
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
Worker自己实现有关锁的方法
public void lock() { acquire(1); }
public boolean tryLock() { return tryAcquire(1); }
public void unlock() { release(1); }
public boolean isLocked() { return isHeldExclusively(); }
其中,acquire和release无法重写,所以用的还是aqs中的方法,如下
acquire方法
public final void acquire(int arg) {
//尝试获取锁
if (!tryAcquire(arg) &&
//获取不到加队列
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
release方法
public final boolean release(int arg) {
//尝试释放锁
if (tryRelease(arg)) {
//释放成功弹出队列第一个
Node h = head;
if (h != null && h.waitStatus != 0)
//叫醒队列线程
unparkSuccessor(h);
return true;
}
return false;
}
其中tryRelease(arg)和tryAcquire(arg)两个方法是可以重写的,当然Worker也自己重写了这两个方法,相比于ReentrantLock,这里重写的方法是一个不可重入锁。
protected boolean tryAcquire(int unused) {
//cas将锁状态设置为1
if (compareAndSetState(0, 1)) {
//设置当前线程拥有锁
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
protected boolean tryRelease(int unused) {
//将当前锁程拥有者置空
setExclusiveOwnerThread(null);
//将锁状态无论原来是什么,都设置为0
setState(0);
return true;
}
getTask方法:获取队列中的任务
//获取队列中的任务
private Runnable getTask() {
//标记上次最后一次poll是否超时
boolean timedOut = false; // 最后一次 poll() 超时了吗?
for (;;) {
//获取ctl
int c = ctl.get();
//获取线程池状态
int rs = runStateOf(c);
// 检测队列状态 以及 是否为空,如果SHUTDOWN状态并且对列为空或者超过了SHUTDOWN状态
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
//将workerCount减1并返回null。
decrementWorkerCount();
//以上状态都没有任务需要处理
return null;
}
//获取当前线程池的工作线程数
int wc = workerCountOf(c);
//工人会被淘汰吗?
//allowCoreThreadTimeOut如果为 false(默认),核心线程即使在空闲时也保持活动状态。如果为true,核心线程使用 keepAliveTime 超时等待工作。即允许核心线程超时吗
//前者默认为false,那么只看后者,timed此时就是标记工作线程数是否大于核心线程数
// timed变量用于判断是否需要进行超时控制。
// allowCoreThreadTimeOut默认是false,也就是核心线程不允许进行超时;
// wc > corePoolSize,表示当前线程池中的线程数量大于核心线程数量;
// 对于超过核心线程数量的这些线程,需要进行超时控制
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
//如果(工作线程数超过了最大线程数||(工作线程数是否大于核心线程数&&超时状态))&&(工作线程>1 || 队列为空)
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
//cas删减worker
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
try {
//三目运算符:最后一个元素是否超时
//Y:超时就使用阻塞队列的poll方法保持存货等待有元素后弹出队列
//N:没有超时,那就正常的take出第一个元素
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
//程序健壮性,取出阻塞队列中的任务
if (r != null)
return r;
//如果超过指定时间,那么poll会返回null,此时就不会进入if,那么就表记为超时,将标记色湖之为true
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}
processWorkerExit后续处理方法
private void processWorkerExit(Worker w, boolean completedAbruptly) {
// 如果completedAbruptly值为true,则说明线程执行时出现了异常,需要将workerCount减1;
// 如果线程执行时没有出现异常,说明在getTask()方法中已经已经对workerCount进行了减1操作,这里就不必再减了。
if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
//如果出现异常,那么正在工作的线程量就-1
decrementWorkerCount();
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
//统计完成的任务数
completedTaskCount += w.completedTasks;
// 从workers中移除,也就表示着从线程池中移除了一个工作线程
workers.remove(w);
} finally {
mainLock.unlock();
}
// 根据线程池状态进行判断是否结束线程池
tryTerminate();
int c = ctl.get();
/*
* 当线程池是RUNNING或SHUTDOWN状态时,如果worker是异常结束,那么会直接addWorker;
* 如果allowCoreThreadTimeOut=true,并且等待队列有任务,至少保留一个worker;
* 如果allowCoreThreadTimeOut=false,workerCount不少于corePoolSize。
*/
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);
}
}