好了到这里,恭喜你,关于ThreadPoolExecutor的源码解析理解得差不多了。接下来剩下几个常用的api方法:submit() 、 shutdown()/shutdownNow() 顺便看一下吧,他们的逻辑也是都非常简单。
关闭线程池:shutdown/shutdownNow关闭线程池有两个方法:
shutdown:设置线程池的状态为shutdown,同时尝试中断所有空闲线程,但是会等待队列中的任务执行结束再终止线程池。
shutdownNow:设置线程池的状态为stop,同时尝试中断所有空闲线程,不会等待队列中的任务完成,正在执行中的线程执行结束,线程池马上进入terminated状态。
我们各自来看一下:
// 关闭后队列中的任务依旧会被执行,但是不会再添加新的任务 public void shutdown() { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { checkShutdownAccess(); // 设置状态为shutdown advanceRunState(SHUTDOWN); // 尝试中断所有空闲的worker interruptIdleWorkers(); // 回调方法,这个方法是个空方法,ScheduledThreadPoolExecutor中重写了该方法 onShutdown(); } finally { mainLock.unlock(); } // 尝试设置线程池状态为terminated tryTerminate(); }再看一下另一个方法shutdownNow:
// 关闭后队列中剩余的任务不会被执行 // 会把剩下的任务返回交给开发者去处理 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; }最后再来看一下和 execute()不同的提交任务方法:submit。
提交任务:submit()submit方法并不是ThreadPoolExecutor实现的,而是AbstractExecutorService,如下:
// runnable没有返回值,创建FutureTask的返回参数传入null public Future<?> submit(Runnable task) { if (task == null) throw new NullPointerException(); RunnableFuture<Void> ftask = newTaskFor(task, null); execute(ftask); return ftask; } // 有参数返回值的runnable // 最终也是构造一个callable来执行,把返回值设置为result 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; } // callable本身就拥有返回值 public <T> Future<T> submit(Callable<T> task) { if (task == null) throw new NullPointerException(); RunnableFuture<T> ftask = newTaskFor(task); execute(ftask); return ftask; }他们的逻辑都几乎一样:调用newTaskFor方法来构造一个Future对象并返回。我们看到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); }可以看到这个方法很简单:构造一个FutureTask并返回,FutureTask也是Future接口目前唯一的实现类。
更加具体关于Future的内容就不展开了,有兴趣的读者可以去了解一下。
最后好了到这里,关于ThreadPoolExecutor的源码分析内容就讲完了。最后让我们再回顾一下吧:
ThreadPoolExecutor的整个执行流程从execute方法开始,他会根据具体的情况,采用合适的执行方案
线程被封装在worker对象中,worker对象通过runWorker方法,会一直不断地调用getTask方法来调用队列的poll或take方法获取任务
当需要退出一个worker时,只要getTask方法返回null即可退出
当线程池关闭时,会根据不同的关闭方法,等待所有的线程执行完成,然后关闭线程池。