如何正确关闭线程池
如何正确关闭线程池
首先有5种在ThreadPoolExecutor中涉及的关闭线程的方法,我们挨个来分析。
void shutdown()
它可以安全的关闭一个线程池,调用shutdown()方法后,线程池不会立刻关闭,而是等执行完正在执行的任务和队列中等待的任务后才彻底关闭,而且调用shutdown()方法后,如果还有新的任务继续到来,那么线程池会根据拒绝策略直接拒绝后面来的新任务.
boolean isShutdown()
这个方法可以返回ture或者false来判断是否已经开始了关闭工作,也就是是否执行了shutdown或者shutdownNow方法,调用isShutdown()方法后如果返回true,并不代表线程池已经彻底关闭了,仅仅代表开始了关闭流程,仍然可能有线程正在执行任务,队列里也可能有任务等待被执行.
boolean isTerminated()
这个方法可以检测是否真正关闭了,不仅代表线程池是否已经关闭,同时也代表线程池中的所有任务是否已经都执行完毕,比如已经调用了shutdown()方法,但是有一个线程正在执行任务,则此时调用isShutdown方法返回true,而调用isTerminated方法便返回false,,因为线程池中还有任务再执行,线程池没有真正关闭,直到所有线程都执行完毕,任务都执行完毕,再调用isTermainted就返回ture.
boolean awaitTermination(long timeout,TimeUnit unit),throws IntereuptedException
awaitTermination并不是用来关闭线程池的,而是用来判断线程池状态的,参数需要传入一个时间,如果我们设置10秒钟,那么会有以下几种情况:
- 等待期间,线程池已经关闭且所有提交的任务都执行完毕,那么方法就返回ture,相当于线程池真正关闭了.
- 等待时间超时后,第一种情况未发生,那么方法返回false.
- 等待时间中,执行任务的线程被中断了,方法会抛出InterruptedException异常.
所以综上可以看出,调用 awaitTermination 方法后当前线程会尝试等待一段指定的时间,如果在等待时间内,线程池已关闭并且内部的任务都执行完毕了,也就是说线程池真正“终结”了,那么方法就返回 true,否则超时返回 fasle,我们则可以根据 awaitTermination() 返回的布尔值来判断下一步应该执行的操作。
List<Runnable> shutdownNow()
调用shutdownNow()方法后,首先会给所有线程池中的线程发送interrupt中断信号,尝试中断这些任务的执行,
然后就任务队列中在等待被执行的任务转移到一个List中并返回,我们可以再根据List做一些操作,shutdownNow() 的源码如下所示:
public List<Runnable> shutdownNow() { List<Runnable> tasks; final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { checkShutdownAccess(); //转换线程运行状态 advanceRunState(STOP); //让每一个已经启动的线程都中断,如果被中断的线程对于中断信号不理不睬 //那么依然有可能导致任务不会停止 interruptWorkers(); //将队列中任务放入tasks集合中,并返回. tasks = drainQueue(); } finally { mainLock.unlock(); } tryTerminate(); return tasks; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix