在日常使用线程池的过程中,怎样合理地关闭线程池,最小程度地影响业务,shutdown 和 shutdownNow 该如何选择?
对比过后,两个方法,设置的线程池状态不同,分别为 SHUTDOWN 和 STOP,中断线程的细节不同,分别是中断 idle 工作线程和中断所有工作线程。
怎么判断工作线程是否空闲呢?原来工作线程执行任务的时候,会加锁,任务执行完成后释放锁。
中断 idle 线程时,尝试获取锁,获取锁成功则认定线程 idle
工作线程 idle,它必然阻塞在 getTask 处,它被中断后,会根据线程池状态返回 null task,完成工作线程的退出。
总结:
shutdown 无法提交新任务,中断空闲工作线程,等待队列中的任务执行完毕。
shutdownNow 无法提交新任务,中断所有线程,返回队列中的任务。
可以看出,shutdown 方法已经足够优雅了,那么还有哪些地方需要增强呢?如果线程池队列中堆积的任务太多,导致线程池关闭的时间太长,可以手动地将队列中的任务全部移除(当然前提是可以获取到队列的引用),然后再关闭线程池;同时还可以结合 awaitTermination 方法等待线程池关闭。如果是应用程序停止时关闭线程池,需要注意如果线程池线程是后台线程,则有可能导致关闭异常,在前台线程中调用 shutdown 后,接着调用 awaitTermination 进行等待。
那什么时候可以使用 shutdownNow 呢,如果要快速关闭线程池,用这个方法似乎更优,但是它会中断工作线程,而我们的业务代码不确定哪个地方会阻塞(RPC 调用,加锁等待,读取数据库),很多阻塞代码可能会响应中断,抛出异常,导致任务执行异常,所以慎用。