为了阅读方便,部分代码有所简化
了解源码最主要的就是找入口,入口找到了,就可以一步步往下面看了。那么线程池的入口在哪里呢?当然是从创建线程池的地方开始。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
RejectedExecutionHandler handler)
corePoolSize:线程池核心线程数量
maximumPoolSize:线程池最大线程数量
keepAliverTime:当活跃线程数大于核心线程数时,空闲的多余线程最大存活时间
unit:存活时间的单位
workQueue:存放任务的队列
handler:超出线程范围和队列容量的任务的处理程序
使用线程池的时候是调用了execute方法执行我们创建的线程,下面看execute方法源码
execute(Runnable command)
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
//情况1.核心线程未达到corePoolSize设定的值
if (workerCountOf(c) < corePoolSize) {
//添加工作线程方法
if (addWorker(command, true))
return;
c = ctl.get();
}
//情况2.核心线程已达到corePoolSize设定的值但队里未满
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command); //调用handler超出线程范围和队列容量的任务的处理程序
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//情况3.核心线程已满且队列已满
else if (!addWorker(command, false))
reject(command); //调用handler超出线程范围和队列容量的任务的处理程序
}
//调用handler超出线程范围和队列容量的任务的处理程序
final void reject(Runnable command) {
handler.rejectedExecution(command, this);
}
可以看到使用线程池的时候会有三种情况
我们一种一种来说,先说第一种情况
情况1,核心线程未达到corePoolSize设定的值:
可以看到当核心线程未满时,会调用addWorker()方法来添加核心线程,下面看addWorker()方法
private boolean addWorker(Runnable firstTask, boolean core) {
Worker w = null;
for (;;) {
int wc = workerCountOf(c);
//判断核心线程数是否大于maximumPoolSize.如果大于的话就返回。
if (wc >= CAPACITY ||wc >= (core ? corePoolSize : maximumPoolSize))
return false;
}
try {
//把执行任务包装成一个Worker对象,这里的Worker对象实际上也是一个线程
w = new Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
int rs = runStateOf(ctl.get());
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive())
throw new IllegalThreadStateException();
//把前面的Worker对象添加的workers中
workers.add(w);
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
//启动Worker线程
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
Worker类也是一个线程对象
private final class Worker
extends AbstractQueuedSynchronizer
implements Runnable
{
public void run() {
runWorker(this);
}
}
可以看到Worker也是实现了Runnable接口,上面的t.start()调用的实际上是启动了Worker线程,也就是调用了此处的run()方法,run()调用了runWorker()方法,下面看runWorker()方法
final void runWorker(Worker w) {
Runnable task = w.firstTask;
try {
//循环从workQueue中取出任务并执行。getTask()方法在workQueue中没有任务的时候会堵塞,直到有任务加入或超时结束退出。
//firstTask为前面传进来的任务,getTask为从workQueue获取任务执行
while (task != null || (task = getTask()) != null) {
try {
task.run();
} finally {
//省略其他代码
}
}
} finally {
processWorkerExit(w, completedAbruptly);
}
}
private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out?
for (;;) {
try {
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();//会堵塞线程,直到workQueue中有新任务的加入
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}
可以看到有个while循环,这个while循环干的事就是先执行传进来的Worker中封装的线程,然后通过getTask()循环把队列中的任务取出来执行。如果getTask方法结束,返回的是null,runWorker循环结束,执行processWorkerExit方法。
至此,该线程结束自己的使命,从线程池中“消失”。
情况2:
比较简单,就是调用workQueue的offer方法把线程加入到队列中,供已经存在的核心线程取出来执行。
情况3:
会再次尝试调用addWorker()再次添加工作线程,但是会限制在maximumPoolSize之内。