一个线程在创建的时候会指定一个线程任务,当执行完这个线程任务之后,线程自动销毁。但是线程池可以复用线程,即一个线程执行完线程任务后不销毁,继续执行另外的线程任务。
ThreadPoolExecutor在创建线程时,会将线程封装成工作线程worker,并放入工作线程组中,然后这个worker反复从阻塞队列中拿任务去执行。
private boolean addWork(Runnable firstTask, boolean core){
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))
// 1. 如果core是ture,证明需要创建的线程为核心线程,则先判断当前线程是否大于最大核心线程数目
// 2. 如果core是false,证明需要创建的是非核心线程,则先判断当前线程数是否大于最大线程数目
// 如果不小于则返回false
return false;
if (compareAndIncrementWorkerCount(c))
break retry;
c = ctl.get(); // re-read ctl
if (runStateOf(c) != rs)
continue retry;
}
}
addWork上半部分主要是判断当前线程数是否超过corePoolSize和MaximumPoolSize,超过了就返回false。
// ThreadPoolExecutor.addWork()方法下半部分
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try{
// 1.创建一个worker对象
w = new Worker(firstTask);
// 2.实例化一个Thread对象
final Thread t = w.thread;
if (t != null){
// 3.线程池全局锁
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try{
// Rechek while holding lock
// Back out on ThreadFactory failure of 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){
// 4.启动这个线程
t.start(); // JVM调用Worker中的run()方法,由于Worker实现了Runnable
workerStarted = true;
}
}
} finally{
if (!workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
创建worker对象,并初始化一个Thread对象,然后启动这个线程对象。
private final class Worker extends AbstractQueuedSynchronizer implements Runnalbe{
final Thread thread;
Runable firstTask;
valatile long completedTasks; // 每个线程任务计数器
Worker(Runnable firstTask){
setState(-1); // 禁止中断直到执行任务
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this); // 创建了一个线程
}
public void run(){
runWorker(this);
}
...
}
Worker类实现了Runnable接口,所以Worker也是一个线程任务。在构造方法中,创建了一个线程,线程的任务就是自己。故addWorker方法调用addWorker方法源码下半部分中t.start(),会触发Worker类的run方法被JVM调用。
// Worker.runWorker方法源码
final void runWorker(Worker w){
Thread wt = Thread.currentThread(); // 获取当前的线程
Runable task = w.firtTask;
w.firstTask = null;
// 1.线程启动之后,通过unlock方法释放锁
w.unlock; // 允许打断
boolean completeAbruptly = ture;
try{
// 2. Worker执行firstTask或从workQueue中获取任务,如果getTask方法不返回null,循环一直继续
while(task != null || (task = getTask()) != null){
// 2.1 进行加锁操作,保证thread不被其他线程中断(除非线程池被中断)
w.lock();
// 如果线程池停止,确保线程被打断
// 如果没有停止,确保线程不被打断,这需要再检查去处理shutdownNow方法
// 2.2检查线程池状态,如果线程池处于中断状态,当前线程将中断
if ((runStateAtLesast(ctl.get(), STOP) || (Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) && !wt.isInterrupted())
wt.interrupted(); // 当前线程中断
try{
//2.3 执行beforeExecute
beforeExecute(wt, task);
Throwable thrown = null;
try{
// 2.4 执行任务
task.run();
// 捕获执行过程中的异常
} catch(RuntimeException x){
thrown = x;
throw x;
} catch(Error x){
thrown = x;
throw x;
} catch(Throwable x){
throw n= x;
throw new Error(x);
} finally{
// 2.5 执行afterExecute方法
afterExecute(task, thrown);
}
} finally{
task = null;
w.completeTasks++;
// 2.6 解锁操作
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
首先去执行创建这个worker时就有的任务,当执行完当前任务后,worker会通过getTask方法从workQueue中获取任务然后通过task.run()执行任务,从而达到复用线程的目的。
private Runnable getTask() {
boolean timedOut = false; // 最后一个弹出是否超时
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}
int wc = workerCountOf(c);
// Are workers subject to culling?
// 1. allowCoreThreadTimeOut变量默认是false,核心线程即使空闲也不会销毁
// 如果为true,核心线程在keepAliveTime内仍空闲就会被销毁
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
// 2. 如果当前线程总数超过了最大线程数,并且任务队列已经空了,这是需要递减worker数量
// 如果有设置允许线程超时或者线程数量超过了核心线程数量,
// 并且线程在规定时间内均未poll到任务且队列为空则递减worker数量
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
try {
// 3.如果timed为true则会调用workQueue的poll方法
// 超时时间是keepAliveTime,如果超过这个这个时间poll返回null,while就会退出,线程执行完了
// 如果timed为false,则会调用workQueue的take方法阻塞在当前。
// 每个WorkQueue会实现poll方法和take方法
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}
核心线程会一直卡在workQueue.take方法,被阻塞并挂起,不会占用CPU资源,直到拿到Runnable然后返回(如果allowCoreThreadTimeOut设置true,那么核心线程会去调用poll方法,因为poll会返回null,所以这时候核心线程满足超时条件会被销毁).