在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线程池

在 .NET 环境中优雅地缩小动态生成的 javascript? [关闭]

如何在 Netty 中的 ssl 握手之前优雅地关闭频道?

如何优雅地关闭资源

Pub\Sub Python 客户端 - 优雅地关闭订阅者

优雅地中止 FileStream 写入循环