在webapp中正常关闭ExecutorService?
在我的webapp中,我创建了一个使用具有固定大小ThreadPool的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线程已经谈到了这一点,但我找不到一个干净的方法来处理这个问题。
我是否应该按照Tim-bender的建议使用ShutdownHook
来正常关闭线程和执行程序 ? 或者我应该使用CachedThreadPool吗?
关闭挂钩在Tomcat中不是一个好方法,因为:
-
它将关闭池太晚(关机时),Tomcat已经警告过你没有关闭资源
-
您实际上想要在取消部署应用程序时关闭该池,以便重新部署工作(否则每个应用程序将创建新池,并且它们将仅在完全关闭时关闭)
-
关闭线程池可能需要一些时间(见下文),shutdown hook应该尽可能快
更好的地方是ServletContextListener.contextDestroyed()
。 记住你必须同时shutdownNow()
池(取消运行并拒绝新任务)和awaitTermination()
等待已经运行的任务完成并停止所有线程。
除了Tomasz建议您还可以使用CachedThreadPool
未使用60秒的线程将终止并从缓存中删除。 因此,长时间闲置的池不会消耗任何资源
因此,一个非常好的解决方案是使用CachedThreadPool
并在ServletContextListener.contextDestroyed()
关闭它。
- 在ExecutorService中hibernate一个线程(Java / Clojure)
- 如何立即停止使用ExecutorService启动的任务?
- 如何实现或找到线程安全的CompletionService的等价物?
- Java执行程序:等待任务终止。
- 一旦我的线程中断,我怎么能中断RestTemplate调用?
- 如何在java中设置Socket写入时间?
- invokeAll()不愿意接受Collection <Callable >
- Java:带有Callables的ExecutorService:invokeAll()和future.get() – 结果是否正确?
- ExecutorService,如何知道所有线程何时完成而不阻塞主线程?