在webapp中优雅地关闭ExecutorService?
Posted
技术标签:
【中文标题】在webapp中优雅地关闭ExecutorService?【英文标题】:Shutdown ExecutorService gracefully in webapp? 【发布时间】:2012-09-30 16:53:59 【问题描述】:在我的 web 应用程序中,我创建了一个使用具有固定大小线程池的 ExecutorService
的服务。我在整个应用程序生命周期内重复使用相同的ExecutorService
。
private static ExecutorService pool = Executors.newFixedThreadPool(8);
所有都在 Tomcat 中运行,关闭时出现以下错误:
appears to have started a thread named [pool-1-thread-1] but has failed to stop it. This is very likely to create a memory leak.
我确实意识到在关闭 tomcat 之前我需要关闭 ExecutorService。 Soms SO线程已经谈到了这个,但我找不到一个干净的方法来处理这个。
我应该按照Graceful shutdown of threads and executor 中建议的@Tim-bender 使用ShutdownHook
吗?还是应该改用 CachedThreadPool?
【问题讨论】:
【参考方案1】:关闭挂钩在 Tomcat 中不是一个好方法,因为:
它会太晚关闭池(关闭时),Tomcat 已经警告您未关闭的资源
您实际上希望在取消部署应用程序时关闭该池,以便重新部署工作(否则每个应用程序将创建新池,并且它们都将仅在完全关闭时关闭)
关闭线程池可能需要一些时间(见下文),关闭钩子应该尽可能快
更好的地方是ServletContextListener.contextDestroyed()
。请记住,您必须同时 shutdownNow()
池(取消运行并拒绝新任务)和 awaitTermination()
等待已经运行的任务完成并停止所有线程。
【讨论】:
正是我需要知道的【参考方案2】:除了 Tomasz 的建议,您还可以使用 CachedThreadPool
60 秒内未使用的线程将被终止并从缓存中删除。因此,闲置时间足够长的池不会消耗任何资源
所以一个非常好的解决方案是使用CachedThreadPool
并在ServletContextListener.contextDestroyed()
中关闭它。
【讨论】:
以上是关于在webapp中优雅地关闭ExecutorService?的主要内容,如果未能解决你的问题,请参考以下文章
如果优雅地关闭ExecutorService提供的java线程池