Java线程池ThreadPoolExecutor源码分析
class DirectExecutor implements Executor{ public void execute(Runnable r){ r.run();// 这里不是用的new Thread(r).start(),也就是说没有启动任何一个新的线程。 } }
每个任务提交进来后,直接启动一个新的线程来执行这个任务:
class ThreadPerTaskExecutor implements Executor{ public void execute(Runnable r){ new Thread(r).start(); // 每个任务都用一个新的线程来执行 } }
class SerialExecutor implements Executor { // 任务队列 final Queue<Runnable> tasks = new ArrayDeque<Runnable>(); // 这个才是真正的执行器 final Executor executor; // 当前正在执行的任务 Runnable active; // 初始化的时候,指定执行器 SerialExecutor(Executor executor) { this.executor = executor; } // 添加任务到线程池: 将任务添加到任务队列,scheduleNext 触发执行器去任务队列取任务 public synchronized void execute(final Runnable r) { tasks.offer(new Runnable() { public void run() { try { r.run(); } finally { scheduleNext(); } } }); if (active == null) { scheduleNext(); } } protected synchronized void scheduleNext() { if ((active = tasks.poll()) != null) { // 具体的执行转给真正的执行器 executor executor.execute(active); } } }
public interface ExecutorService extends Executor { void shutdown(); List<Runnable> shutdownNow(); boolean isShutdown(); boolean isTerminated(); boolean awaitTermination(long timeout, TimeUnit unit) throws InteruptedException; <T> Future<T> submit(Callable<T> task); <T> Future<T> submit(Runnable task, T result); Future<?> submit(Runnable task); <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException; <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException; <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException; <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; }
一般我们定义一个线程池的时候,往往都是使用这个接口:
public abstract class AbstractExecutorService implements ExecutorService { // RunnableFuture 是用于获取执行结果的,我们常用它的子类 FutureTask // 下面两个 newTaskFor 方法用于将我们的任务包装成 FutureTask 提交到线程池中执行 protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) { return new FutureTask<T>(runnable, value); } protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) { return new FutureTask<T>(callable); } // 提交任务 public Future<?> submit(Runnable task) { if (task == null) throw new NullPointerException(); // 1. 将任务包装成 FutureTask RunnableFuture<Void> ftask = newTaskFor(task, null); // 2. 交给执行器执行,execute 方法由具体的子类来实现 // 前面也说了,FutureTask 间接实现了Runnable 接口。 execute(ftask); return ftask; } public <T> Future<T> submit(Runnable task, T result) { if (task == null) throw new NullPointerException(); // 1. 将任务包装成 FutureTask RunnableFuture<T> ftask = newTaskFor(task, result); // 2. 交给执行器执行 execute(ftask); return ftask; } public <T> Future<T> submit(Callable<T> task) { if (task == null) throw new NullPointerException(); // 1. 将任务包装成 FutureTask RunnableFuture<T> ftask = newTaskFor(task); // 2. 交给执行器执行 execute(ftask); return ftask; } // 此方法目的:将 tasks 集合中的任务提交到线程池执行,任意一个线程执行完后就可以结束了 // 第二个参数 timed 代表是否设置超时机制,超时时间为第三个参数, // 如果 timed 为 true,同时超时了还没有一个线程返回结果,那么抛出 TimeoutException 异常 private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks, boolean timed, long nanos) throws InterruptedException, ExecutionException, TimeoutException { if (tasks == null) throw new NullPointerException(); // 任务数 int ntasks = tasks.size(); if (ntasks == 0) throw new IllegalArgumentException(); // List<Future<T>> futures= new ArrayList<Future<T>>(ntasks); // ExecutorCompletionService 不是一个真正的执行器,参数 this 才是真正的执行器 // 它对执行器进行了包装,每个任务结束后,将结果保存到内部的一个 completionQueue 队列中 // 这也是为什么这个类的名字里面有个 Completion 的原因吧。 ExecutorCompletionService<T> ecs = new ExecutorCompletionService<T>(this); try { // 用于保存异常信息,此方法如果没有得到任何有效的结果,那么我们可以抛出最后得到的一个异常 ExecutionException ee = null; long lastTime = timed ? System.nanoTime() : 0; Iterator<? extends Callable<T>> it = tasks.iterator(); // 首先先提交一个任务,后面的任务到下面的 for 循环一个个提交 futures.add(ecs.submit(it.next())); // 提交了一个任务,所以任务数量减 1 --ntasks; // 正在执行的任务数(提交的时候 +1,任务结束的时候 -1) int active = 1; for (;;) { // ecs 上面说了,其内部有一个 completionQueue 用于保存执行完成的结果 // BlockingQueue 的 poll 方法不阻塞,返回 null 代表队列为空 Future<T> f = ecs.poll(); // 为 null,说明刚刚提交的第一个线程还没有执行完成 // 在前面先提交一个任务,加上这里做一次检查,也是为了提高性能 if (f == null) { if (ntasks > 0) { --ntasks; futures.add(ecs.submit(it.next())); ++active; } // 这里是 else if,不是 if。这里说明,没有任务了,同时 active 为 0 说明 // 任务都执行完成了。其实我也没理解为什么这里做一次 break? // 因为我认为 active 为 0 的情况,必然从下面的 f.get() 返回了 // 2018-02-23 感谢读者 newmicro 的 comment, // 这里的 active == 0,说明所有的任务都执行失败,那么这里是 for 循环出口 else if (active == 0) break; // 这里也是 else if。这里说的是,没有任务了,但是设置了超时时间,这里检测是否超时 else if (timed) { // 带等待的 poll 方法 f = ecs.poll(nanos, TimeUnit.NANOSECONDS); // 如果已经超时,抛出 TimeoutException 异常,这整个方法就结束了 if (f == null) throw new TimeoutException(); long now = System.nanoTime(); nanos -= now - lastTime; lastTime = now; } // 这里是 else。说明,没有任务需要提交,但是池中的任务没有完成,还没有超时(如果设置了超时) // take() 方法会阻塞,直到有元素返回,说明有任务结束了 else f = ecs.take(); } /* * 我感觉上面这一段并不是很好理解,这里简单说下。 * 1. 首先,这在一个 for 循环中,我们设想每一个任务都没那么快结束, * 那么,每一次都会进到第一个分支,进行提交任务,直到将所有的任务都提交了 * 2. 任务都提交完成后,如果设置了超时,那么 for 循环其实进入了“一直检测是否超时” 这件事情上 * 3. 如果没有设置超时机制,那么不必要检测超时,那就会阻塞在 ecs.take() 方法上, 等待获取第一个执行结果 * 4. 如果所有的任务都执行失败,也就是说 future 都返回了, 但是 f.get() 抛出异常,那么从 active == 0 分支出去(感谢 newmicro 提出) // 当然,这个需要看下面的 if 分支。 */ // 有任务结束了 if (f != null) { --active; try { // 返回执行结果,如果有异常,都包装成 ExecutionException return f.get(); } catch (ExecutionException eex) { ee = eex; } catch (RuntimeException rex) { ee = new ExecutionException(rex); } } }// 注意看 for 循环的范围,一直到这里 if (ee == null) ee = new ExecutionException(); throw ee; } finally { // 方法退出之前,取消其他的任务 for (Future<T> f : futures) f.cancel(true); } } public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException { try { return doInvokeAny(tasks, false, 0); } catch (TimeoutException cannotHappen) { assert false; return null; } } public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return doInvokeAny(tasks, true, unit.toNanos(timeout)); } // 执行所有的任务,返回任务结果。 // 先不要看这个方法,我们先想想,其实我们自己提交任务到线程池,也是想要线程池执行所有的任务 // 只不过,我们是每次 submit 一个任务,这里以一个集合作为参数提交 public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException { if (tasks == null) throw new NullPointerException(); List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size()); boolean done = false; try { // 这个很简单 for (Callable<T> t : tasks) { // 包装成 FutureTask RunnableFuture<T> f = newTaskFor(t); futures.add(f); // 提交任务 execute(f); } for (Future<T> f : futures) { if (!f.isDone()) { try { // 这是一个阻塞方法,直到获取到值,或抛出了异常 // 这里有个小细节,其实 get 方法签名上是会抛出 InterruptedException 的 // 可是这里没有进行处理,而是抛给外层去了。此异常发生于还没执行完的任务被取消了 f.get(); } catch (CancellationException ignore) { } catch (ExecutionException ignore) { } } } done = true; // 这个方法返回,不像其他的场景,返回 List<Future>,其实执行结果还没出来 // 这个方法返回是真正的返回,任务都结束了 return futures; } finally { // 为什么要这个?就是上面说的有异常的情况 if (!done) for (Future<T> f : futures) f.cancel(true); } } // 带超时的 invokeAll,我们找不同吧 public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException { if (tasks == null || unit == null) throw new NullPointerException(); long nanos = unit.toNanos(timeout); List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size()); boolean done = false; try { for (Callable<T> t : tasks) futures.add(newTaskFor(t)); long lastTime = System.nanoTime(); Iterator<Future<T>> it = futures.iterator(); // 每提交一个任务,检测一次是否超时 while (it.hasNext()) { execute((Runnable)(it.next())); long now = System.nanoTime(); nanos -= now - lastTime; lastTime = now; // 超时 if (nanos <= 0) return futures; } for (Future<T> f : futures) { if (!f.isDone()) { if (nanos <= 0) return futures; try { // 调用带超时的 get 方法,这里的参数 nanos 是剩余的时间, // 因为上面其实已经用掉了一些时间了 f.get(nanos, TimeUnit.NANOSECONDS); } catch (CancellationException ignore) { } catch (ExecutionException ignore) { } catch (TimeoutException toe) { return futures; } long now = System.nanoTime(); nanos -= now - lastTime; lastTime = now; } } done = true; return futures; } finally { if (!done) for (Future<T> f : futures) f.cancel(true); } } }
//高3位表示线程池状态, 后29位表示线程个数,记录线程池状态和线程数量 private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); ////线程数量统计位数29 Integer.SIZE=32 private static final int COUNT_BITS = Integer.SIZE - 3; //容量 000 11111111111111111111111111111 private static final int CAPACITY = (1 << COUNT_BITS) - 1; //运行状态 例:11100000000000000000000000000000 private static final int RUNNING = -1 << COUNT_BITS; //关闭状态 例:00000000000000000000000000000000 private static final int SHUTDOWN = 0 << COUNT_BITS; //停止状态 例:00100000000000000000000000000000 private static final int STOP = 1 << COUNT_BITS; //整理状态 例:01000000000000000000000000000000 private static final int TIDYING = 2 << COUNT_BITS; //终止状态 例:01100000000000000000000000000000 private static final int TERMINATED = 3 << COUNT_BITS; //获取运行状态(获取前3位) private static int runStateOf(int c) { return c & ~CAPACITY; } //获取线程个数(获取后29位) private static int workerCountOf(int c) { return c & CAPACITY; } private static int ctlOf(int rs, int wc) { return rs | wc; RUNNING = 0:接受新任务并且处理阻塞队列里的任务 SHUTDOWN = 1:拒绝新任务但是处理阻塞队列里的任务 STOP = 2:拒绝新任务并且抛弃阻塞队列里的任务同时会中断正在处理的任务 TIDYING :所有任务都执行完(包含阻塞队列里面任务)当前线程池活动线程为0,将要调用terminated方法 TERMINATED = 3:终止状态。terminated方法调用完成以后的状态
线程池状态转换:
//任务队列 private final BlockingQueue<Runnable> workQueue; //工作者集合 private final HashSet<Worker> workers = new HashSet<Worker>(); //线程达到的最大值 private int largestPoolSize; //已完成任务总数 private long completedTaskCount; //线程工厂 private volatile ThreadFactory threadFactory; //拒绝策略 private volatile RejectedExecutionHandler handler; //闲置线程存活时间 private volatile long keepAliveTime; //是否允许核心线程超时 private volatile boolean allowCoreThreadTimeOut; //核心线程数量 private volatile int corePoolSize; //最大线程数量 private volatile int maximumPoolSize; //默认拒绝策略 private static final RejectedExecutionHandler defaultHandler = new AbortPolicy();
//核心构造器 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) { throw new IllegalArgumentException(); } if (workQueue == null || threadFactory == null || handler == null) { throw new NullPointerException(); } this.corePoolSize = corePoolSize; //设置核心线程数量 this.maximumPoolSize = maximumPoolSize; //设置最大线程数量 this.workQueue = workQueue; //设置存放任务队列 this.keepAliveTime = unit.toNanos(keepAliveTime); //设置非核心线程存活时间 this.threadFactory = threadFactory; //设置用来生产线程的工厂 this.handler = handler; //设置不能再放入任务时候执行的拒绝策略 }
ThreadPoolExecutor有多个构造器,所有的构造器都会调用上面的核心构造器。通过核心构造器我们可以为线程池设置不同的参数,由此线程池也能表现出不同的特性。
public Future<?> submit(Runnable task) { if (task == null) throw new NullPointerException(); RunnableFuture<Void> ftask = newTaskFor(task, null); execute(ftask); return ftask; } public <T> Future<T> submit(Runnable task, T result) { if (task == null) throw new NullPointerException(); RunnableFuture<T> ftask = newTaskFor(task, result); execute(ftask); return ftask; } public <T> Future<T> submit(Callable<T> task) { if (task == null) throw new NullPointerException(); RunnableFuture<T> ftask = newTaskFor(task); execute(ftask); return ftask; }
submit 方法中,参数是 Runnable 类型(也有Callable 类型),这个参数不是用于new Thread(runnable).start()中的,也就是说此处的这个参数不是用于启动线程的,这里指的是任务,任务要做的事情是 run()方法里面定义的或 Callable 中的 call() 方法里面定义的。
-
调用submit方法,传入Runnable或者Callable对象
-
判断传入的对象是否为null,为null则抛出异常,不为null继续流程
-
将传入的对象转换为RunnableFuture对象
-
执行execute方法,传入RunnableFuture对象
-
返回RunnableFuture对象
//核心执行方法 public void execute(Runnable command) { if (command == null) throw new NullPointerException(); int c = ctl.get(); //线程数若小于corePoolSize则新建核心工作者 if (workerCountOf(c) < corePoolSize) { if (addWorker(command, true)) return; c = ctl.get(); } //否则将任务放到任务队列 if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); //若不是running状态则将该任务从队列中移除 if (!isRunning(recheck) && remove(command)) { //成功移除后再执行拒绝策略 reject(command); //若线程数为0则新增一个非核心线程 }else if (workerCountOf(recheck) == 0) { addWorker(null, false); } //若队列已满则新增非核心工作者 }else if (!addWorker(command, false)) { //若新建非核心线程失败则执行拒绝策略 reject(command); } }
-
调用execute方法,传入Runable对象
-
判断传入的对象是否为null,为null则抛出异常,不为null继续流程
-
获取当前线程池的状态和线程个数变量
-
判断当前线程数是否小于核心线程数,是走流程5,否则走流程6
-
添加线程数,添加成功则结束,失败则重新获取当前线程池的状态和线程个数变量,
-
判断线程池是否处于RUNNING状态,是则添加任务到阻塞队列,否则走流程10,添加任务成功则继续流程7
-
重新获取当前线程池的状态和线程个数变量
-
重新检查线程池状态,不是运行状态则移除之前添加的任务,有一个false走流程9,都为true则走流程11
-
检查线程池线程数量是否为0,否则结束流程,是调用addWorker(null, false),然后结束
-
调用!addWorker(command, false),为true走流程11,false则结束
-
调用拒绝策略reject(command),结束
//工作者类 private final class Worker extends AbstractQueuedSynchronizer implements Runnable { //关联线程 final Thread thread; //初始任务 Runnable firstTask; //完成任务数 volatile long completedTasks; //构造器 Worker(Runnable firstTask) { //抑制中断直到runWorker setState(-1); //设置初始任务 this.firstTask = firstTask; //设置关联线程 this.thread = getThreadFactory().newThread(this); } public void run() { runWorker(this); } //判断是否占有锁, 0代表未占用, 1代表已占用 protected boolean isHeldExclusively() { return getState() != 0; } //尝试获取锁 protected boolean tryAcquire(int unused) { if (compareAndSetState(0, 1)) { setExclusiveOwnerThread(Thread.currentThread()); return true; } return false; } //尝试释放锁 protected boolean tryRelease(int unused) { setExclusiveOwnerThread(null); setState(0); return true; } public void lock() { acquire(1); } public boolean tryLock() { return tryAcquire(1); } public void unlock() { release(1); } public boolean isLocked() { return isHeldExclusively(); } //中断关联线程 void interruptIfStarted() { Thread t; //将活动线程和闲置线程都中断 if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) { try { t.interrupt(); } catch (SecurityException ignore) { //ignore } } } }
private boolean addWorker(Runnable firstTask, boolean core) { retry: for (;;) { int c = ctl.get(); int rs = runStateOf(c); //只有以下两种情况会继续添加线程 //1.状态为running //2.状态为shutdown,首要任务为空,但任务队列中还有任务 if (rs >= SHUTDOWN && !(rs == SHUTDOWN && firstTask == null && !workQueue.isEmpty())) { return false; } for (;;) { int wc = workerCountOf(c); //以下三种情况不继续添加线程: //1.线程数大于线程池总容量 //2.当前线程为核心线程,且核心线程数达到corePoolSize //3.当前线程非核心线程,且总线程达到maximumPoolSize if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize)) { return false; } //否则继续添加线程, 先将线程数加一 if (compareAndIncrementWorkerCount(c)) { //执行成功则跳过外循环 break retry; } //CAS操作失败再次检查线程池状态 c = ctl.get(); //如果线程池状态改变则继续执行外循环 if (runStateOf(c) != rs) { continue retry; } //否则表明CAS操作失败是workerCount改变, 继续执行内循环 } } boolean workerStarted = false; boolean workerAdded = false; Worker w = null; try { final ReentrantLock mainLock = this.mainLock; w = new Worker(firstTask); final Thread t = w.thread; if (t != null) { mainLock.lock(); try { int c = ctl.get(); int rs = runStateOf(c); if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) { //如果线程已经开启则抛出异常 if (t.isAlive()) 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 { //如果线程启动失败则回滚操作 if (!workerStarted) { addWorkerFailed(w); } } return workerStarted; }
//工作线程 final void runWorker(Worker w) { //获取当前工作线程 Thread wt = Thread.currentThread(); //获取工作者的初始任务 Runnable task = w.firstTask; //将工作者的初始任务置空 w.firstTask = null; //将同步状态从-1设为0 w.unlock(); boolean completedAbruptly = true; try { //初始任务不为空则执行初始任务, 否则从队列获取任务 while (task != null || (task = getTask()) != null) { //确保获取到任务后才加锁 w.lock(); //若状态大于等于stop, 保证当前线程被中断 //若状态小于stop, 保证当前线程未被中断 //在清理中断状态时可能有其他线程在修改, 所以会再检查一次 if ((runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) && !wt.isInterrupted()) { wt.interrupt(); } 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; retry: //在for循环里自旋 for (;;) { int c = ctl.get(); int rs = runStateOf(c); //以下两种情况会将工作者数减为0并返回null,并直接使该线程终止: //1.状态为shutdown并且任务队列为空 //2.状态为stop, tidying或terminated if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) { decrementWorkerCount(); return null; } boolean timed; //判断是否要剔除当前线程 for (;;) { int wc = workerCountOf(c); //以下两种情况会在限定时间获取任务: //1.允许核心线程超时 //2.线程数大于corePoolSize timed = allowCoreThreadTimeOut || wc > corePoolSize; //以下两种情况不执行剔除操作: //1.上次任务获取未超时 //2.上次任务获取超时, 但没要求在限定时间获取 if (wc <= maximumPoolSize && !(timedOut && timed)) { break; } //若上次任务获取超时, 且规定在限定时间获取, 则将线程数减一 if (compareAndDecrementWorkerCount(c)) { //CAS操作成功后直接返回null return null; } //CAS操作失败后再次检查状态 c = ctl.get(); //若状态改变就从外层循环重试 if (runStateOf(c) != rs) { continue retry; } //否则表明是workerCount改变, 继续在内循环重试 } try { //若timed为true, 则在规定时间内返回 //若timed为false, 则阻塞直到获取成功 //注意:闲置线程会一直在这阻塞 Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take(); //获取任务不为空则返回该任务 if (r != null) { return r; } //否则将超时标志设为true timedOut = true; } catch (InterruptedException retry) { timedOut = false; } } }
工作线程在while循环里不断的通过getTask方法来从任务队列中获取任务,我们看一下getTask方法是怎样获取任务的。进入第一个for循环之后有一个if判断,从这里我们可以看到,如果线程池状态为shutdown,会继续消费任务队列里面的任务;如果线程池状态为stop,则停止消费任务队列里剩余的任务。进入第二个for循环后会给timed变量赋值,由于allowCoreThreadTimeOut变量默认是false,所以timed的值取决于线程数是否大于corePoolSize,小于为false,大于则为true。从任务队列里面获取任务的操作在try块里面,如果timed为true,则调用poll方法进行定时获取;如果timed为flase,则调用take方法进行阻塞获取。也就是说默认情况下,如果线程数小于corePoolSize,则调用take方法进行阻塞获取,即使任务队列为空,工作线程也会一直等待;如果线程数大于corePoolSize,则调用poll方法进行定时获取,在keepAliveTime时间内获取不到任务则会返回null,对应的工作线程也会被移除,但线程数会保持在corePoolSize上。当然如果设置allowCoreThreadTimeOut为true,则会一直通过调用poll方法来从任务队列中获取任务,如果任务队列长时间为空,则工作线程会减少至0。
//删除工作线程 private void processWorkerExit(Worker w, boolean completedAbruptly) { //若非正常完成则将线程数减为0 if (completedAbruptly) { decrementWorkerCount(); } final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { //统计完成的任务总数 completedTaskCount += w.completedTasks; //在这将工作线程移除 workers.remove(w); } finally { mainLock.unlock(); } //尝试终止线程池 tryTerminate(); //再次检查线程池状态 int c = ctl.get(); //若状态为running或shutdown, 则将线程数恢复到最小值 if (runStateLessThan(c, STOP)) { //线程正常完成任务被移除 if (!completedAbruptly) { //允许核心线程超时最小值为0, 否则最小值为核心线程数 int min = allowCoreThreadTimeOut ? 0 : corePoolSize; //如果任务队列还有任务, 则保证至少有一个线程 if (min == 0 && !workQueue.isEmpty()) { min = 1; } //若线程数大于最小值则不新增了 if (workerCountOf(c) >= min) { return; } } //新增工作线程 addWorker(null, false); } }
//平缓关闭线程池 public void shutdown() { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { //检查是否有关闭的权限 checkShutdownAccess(); //将线程池状态设为shutdown advanceRunState(SHUTDOWN); //中断闲置的线程 interruptIdleWorkers(); //对外提供的钩子 onShutdown(); } finally { mainLock.unlock(); } //尝试终止线程池 tryTerminate(); } //立刻关闭线程池 public List<Runnable> shutdownNow() { List<Runnable> tasks; final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { //检查是否有关闭的权限 checkShutdownAccess(); //将线程池状态设为stop advanceRunState(STOP); //中断所有工作线程 interruptWorkers(); //排干任务队列 tasks = drainQueue(); } finally { mainLock.unlock(); } //尝试终止线程池 tryTerminate(); return tasks; }
final void tryTerminate() { for (;;) { int c = ctl.get(); //以下两种情况终止线程池,其他情况直接返回: //1.状态为stop //2.状态为shutdown且任务队列为空 if (isRunning(c) || runStateAtLeast(c, TIDYING) || (runStateOf(c) == SHUTDOWN && !workQueue.isEmpty())) { return; } //若线程不为空则中断一个闲置线程后直接返回 if (workerCountOf(c) != 0) { interruptIdleWorkers(ONLY_ONE); return; } final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { //将状态设置为tidying if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) { try { //线程池终止后做的事情 terminated(); } finally { //将状态设置为终止状态(TERMINATED) ctl.set(ctlOf(TERMINATED, 0)); //唤醒条件队列所有线程 termination.signalAll(); } return; } } finally { mainLock.unlock(); } //若状态更改失败则再重试 } }
public interface ThreadFactory { Thread newThread(Runnable r); } Executors.defaultThreadFactory()实现 public static ThreadFactory defaultThreadFactory() { return new DefaultThreadFactory(); }
static class DefaultThreadFactory implements ThreadFactory { private static final AtomicInteger poolNumber = new AtomicInteger(1);//原子类,线程池编号 private final ThreadGroup group;//线程组 private final AtomicInteger threadNumber = new AtomicInteger(1);//线程数目 private final String namePrefix;//为每个创建的线程添加的前缀 DefaultThreadFactory() { SecurityManager s = System.getSecurityManager(); group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();//取得线程组 namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-"; } public Thread newThread(Runnable r) { Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);//真正创建线程的地方,设置了线程的线程组及线程名 if (t.isDaemon()) t.setDaemon(false); if (t.getPriority() != Thread.NORM_PRIORITY)//默认是正常优先级 t.setPriority(Thread.NORM_PRIORITY); return t; } }