关闭执行器在 Web 应用中优雅地提供服务?

在我的 web 应用程序中,我创建了一个使用固定大小的 ThreadPool 的服务。我在整个应用程序生存期内重复使用相同的内容。ExecutorServiceExecutorService

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之前关闭执行器服务。Soms SO线程已经谈到了这一点,但我找不到一种干净的方法来处理这个问题。

我是否应该在正确关闭线程和执行器中使用建议的@Tim弯曲器?或者我应该改用缓存线程池?ShutdownHook


答案 1

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

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

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

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

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


答案 2

除了Tomasz建议的,你还可以使用CachedThreadPool。

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

因此,一个非常好的解决方案是在 中使用并关闭它。CachedThreadPoolServletContextListener.contextDestroyed()