线程池源码ThreadPoolExecutor分析
shutdown与shutdownNow的对比
/** * Initiates 开始,发起 an orderly 有序的 shutdown in which previously 以前 submitted * tasks are executed, but no new tasks will be accepted. * Invocation 调用 has no additional 额外的 effect 影响 if already shut down. * * <p>This method does not wait for previously submitted tasks to * complete execution. Use {@link #awaitTermination awaitTermination} * to do that. * * @throws SecurityException {@inheritDoc} */
针对之前已经提交的任务进行有序的关闭,不再接收新的任务。如果已经shutdown了,调用这个方法不会有什么影响。该方法不会等待之前已经提交的任务执行完毕,awaitTermination方法才有这个效果。
public void shutdown() { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { checkShutdownAccess(); advanceRunState(SHUTDOWN); interruptIdleWorkers(); onShutdown(); // hook for ScheduledThreadPoolExecutor } finally { mainLock.unlock(); } tryTerminate(); }
其中,private final ReentrantLock mainLock = new ReentrantLock();
使用了锁。
checkShutdownAccess方法进行了安全检查。
/** * If there is a security manager, makes sure caller has * permission to shut down threads in general (see shutdownPerm). * If this passes, additionally makes sure the caller is allowed * to interrupt each worker thread. This might not be true even if * first check passed, if the SecurityManager treats some threads * specially. */ private void checkShutdownAccess() { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkPermission(shutdownPerm); final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { for (Worker w : workers) security.checkAccess(w.thread); } finally { mainLock.unlock(); } } }
然后下面的方法就是设置线程池的状态
/* * Methods for setting control state */ /** * Transitions runState to given target, or leaves it alone if * already at least the given target. * * @param targetState the desired state, either SHUTDOWN or STOP * (but not TIDYING or TERMINATED -- use tryTerminate for that) */ private void advanceRunState(int targetState) { for (;;) { int c = ctl.get(); if (runStateAtLeast(c, targetState) || ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c)))) break; } }
用死循环
这个方法也没什么东西,就是个判断 继续看
private static boolean runStateAtLeast(int c, int s) { return c >= s; }
private static int ctlOf(int rs, int wc) { return rs | wc; }
private static int workerCountOf(int c) { return c & CAPACITY; }
/** * The main pool control state, ctl, is an atomic integer packing * two conceptual 概念 fields * workerCount, indicating 指示 the effective 有效的 number of threads * runState, indicating whether running, shutting down etc 等 * * In order to pack them into one int, we limit workerCount to * (2^29)-1 (about 500 million) threads rather than 而不是(2^31)-1 (2 * billion) otherwise 否则,另 representable 代表. If this is ever an issue 问题 in * the future, the variable can be changed to be an AtomicLong, * and the shift/mask constants constants 常数 below adjusted. But until the need * arises 出现, this code is a bit faster and simpler using an int. * * The workerCount is the number of workers that have been * permitted 允许 to start and not permitted to stop. The value may be * transiently 瞬变 different from the actual number of live threads, * for example when a ThreadFactory fails to create a thread when * asked, and when exiting 退出 threads are still performing 执行 * bookkeeping 记账 before terminating 终止. The user-visible pool size is * reported as the current size of the workers set. * * The runState provides the main lifecycle control, taking on values: * * RUNNING: Accept new tasks and process queued tasks * SHUTDOWN: Don't accept new tasks, but process queued tasks * STOP: Don't accept new tasks, don't process queued tasks, * and interrupt in-progress 执行中 tasks * TIDYING: All tasks have terminated, workerCount is zero, * the thread transitioning 过渡 to state TIDYING * will run the terminated() hook method * TERMINATED: terminated() has completed * * The numerical order among these values matters, to allow * ordered comparisons 比较. The runState monotonically 单调的、无变化的 increases over 增加超过 * time, but need not hit each state. The transitions are: * * RUNNING -> SHUTDOWN * On invocation of shutdown(), perhaps implicitly in finalize() * (RUNNING or SHUTDOWN) -> STOP * On invocation of shutdownNow() * SHUTDOWN -> TIDYING * When both queue and pool are empty * STOP -> TIDYING * When pool is empty * TIDYING -> TERMINATED * When the terminated() hook method has completed * * Threads waiting in awaitTermination() will return when the * state reaches TERMINATED. * * Detecting the transition from SHUTDOWN to TIDYING is less * straightforward than you'd like because the queue may become * empty after non-empty and vice versa during SHUTDOWN state, but * we can only terminate if, after seeing that it is empty, we see * that workerCount is 0 (which sometimes entails a recheck -- see * below). */