线程池关闭源码
线程池的状态如下
private static final int RUNNING = -1 << COUNT_BITS;//111 + 29个0 private static final int SHUTDOWN = 0 << COUNT_BITS;//全是0 private static final int STOP = 1 << COUNT_BITS;//001 + 29个0 private static final int TIDYING = 2 << COUNT_BITS;//010 + 29个0 private static final int TERMINATED = 3 << COUNT_BITS;//011 + 29个0
COUNT_BITS 为29。-1在计算机中的补码是1111 1111,当左移29位后,就是最高的三位是111,剩下29位都是0。
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static int ctlOf(int rs, int wc) { return rs | wc; }
所以这个ctl的初始值就是111 + 29个0
二 shutdown
public void shutdown() { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { checkShutdownAccess();//忽略 advanceRunState(SHUTDOWN);//高三位是000,除非ctl已经比000还大 interruptIdleWorkers(); onShutdown(); // hook for ScheduledThreadPoolExecutor } finally { mainLock.unlock(); } tryTerminate(); }
private void interruptIdleWorkers(boolean onlyOne) { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { for (Worker w : workers) { Thread t = w.thread;//如果线程在工作,或者没有阻塞,那么该方法什么都没有干 if (!t.isInterrupted() && w.tryLock()) {//如果tryLock能够返回true,说明啥说明该线程没有在干活,很可能是在从阻塞队列task,由于队列里没有任务导致阻塞 try { t.interrupt();//执行中断,在worker的getTask方法是会抛出异常的,这会导致线程池中的线程退出 } catch (SecurityException ignore) { } finally { w.unlock(); } } if (onlyOne) break; } } finally { mainLock.unlock(); } }
真正的执行关闭线程逻辑在 tryTerminate,前面只是在打扫战场,打扫的是已经空闲下来的线程,剩下的是
final void tryTerminate() { for (;;) { int c = ctl.get(); if (isRunning(c) || runStateAtLeast(c, TIDYING) || (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))//如果执行过shutdown 前两个判断就都是false,第三个条件如果任务队列不为空,就直接返回 return; if (workerCountOf(c) != 0) { // Eligible to terminate 这个方法的意义,应该是把关闭行为传递下去,但是其实对于工作中的线程不会产生影响,但是如果任务队列为空同时执行过shutdown后, interruptIdleWorkers(ONLY_ONE);//中断可能在take方法阻塞的线程,这样线程就会执行完毕,线程数减一,此时线程池状态是SHUTDOWN,所以即使work数量小于coreSize也不会再次添加worker 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 } }
如果单看这个方法,第一次看人会很懵,因为前两个if,就会发现根本不会关闭线程池。想要理解这个问题,要结合runWorker方法和getTask方法
private Runnable getTask() { boolean timedOut = false; // Did the last poll() time out? 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;//直接返回null }
这样worker线程的循环条件不满足,就会终止,执行finally里面的方法
final void runWorker(Worker w) { ... try { while (task != null || (task = getTask()) != null) { ... } completedAbruptly = false; } finally { processWorkerExit(w, completedAbruptly); } }
把线程remove掉,同时再次执行tryTerminate
private void processWorkerExit(Worker w, boolean completedAbruptly) { if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted decrementWorkerCount(); final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { completedTaskCount += w.completedTasks; workers.remove(w); } finally { mainLock.unlock(); } tryTerminate();
三 shutDownNow
有了shutDown的分析,shutDownNow有几处差别,
1 中断所有的worker,而shutDown是中断空闲worker
2 把任务队列拷贝出来,并清空
3 在上面的 getTask里判断大于等于STOP就不会判断任务队列直接返回null,这样worker线程就会直接退出循环