23

在我的 webapp 中,我创建了一个ExecutorService使用固定大小的 ThreadPool 的服务。我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线程已经谈到了这个,但我找不到一个干净的方法来处理这个。

我应该在优雅关闭线程和执行ShutdownHook程序中使用建议的@Tim-bender吗?或者我应该改用 CachedThreadPool 吗?

4

2 回答 2

25

关闭挂钩在 Tomcat 中不是一个好方法,因为:

  • 它将太晚关闭池(关闭时),Tomcat 已经警告您未关闭的资源

  • 您实际上想在取消部署应用程序时关闭该池,以便重新部署工作(否则每个应用程序将创建新池并且它们都将仅在完全关闭时关闭)

  • 关闭线程池可能需要一些时间(见下文),关闭钩子应该尽可能快

更好的地方是ServletContextListener.contextDestroyed()。请记住,您必须同时shutdownNow()使用池(取消运行和拒绝新任务)并awaitTermination()等待已经运行的任务完成并停止所有线程。

于 2012-10-10T09:02:03.677 回答
7

除了 Tomasz 建议的内容之外,您还可以使用CachedThreadPool

六十秒内未使用的线程将被终止并从缓存中删除。因此,保持空闲足够长时间的池不会消耗任何资源

所以一个很好的解决方案是CachedThreadPoolServletContextListener.contextDestroyed().

于 2012-10-10T09:14:12.733 回答