我开发了一个广泛使用线程的 Webbapp。我们需要定期监控一些资源,然后采取行动。
为了实现这一点,我们开发了一个ThreadManager
,它包装了一个 ScheduledThreadPoolExecutor
。我们允许执行器的任何方法,我们只使用这个管理器来确保每个人都使用相同的线程池实例(管理器是一个单例...)
然后,当我们关闭上下文时,我们有一个 ServletContextListener
负责正确关闭执行程序:
ejecutor.shutdown();
try
{
ejecutor.awaitTermination(10, TimeUnit.SECONDS);
}
catch (InterruptedException ie)
{
Thread.currentThread().interrupt();
}
System.out.println("Llamo al shutdownnow");
ejecutor.shutdownNow();
ejecutor = null;
但是,当我们关闭 tomcat/卸载上下文时,我们会收到很多错误提示:
严重:Web 应用程序 [/qsys] 似乎启动了一个名为 [pool-4-thread-1] 的线程,但未能停止它。这很可能会造成内存泄漏。
如果我们通过询问 Activity 线程数来监控执行器,关闭后,它一直说没有更多的 Activity 线程,但我们继续在 tomcat 上发现相同的错误。
有什么想法吗?
更新:提供了更多信息
挂起的线程是那些在 Executor
中调度的线程。它们都覆盖了 interrupt()
,所以它是这样的:
System.out.println("Me intentan interrumpir!!");
run = false;
super.interrupt();
然后,在 contextDestroyed
期间,我执行了已经提到的关闭...但是系统从中断中退出甚至没有被打印出来!
执行器将 ExecuteExistingDelayedTasksAfterShutdownPolicy
设置为 false...
仍然保持线程存活...
最佳答案
最后,我发现了一些东西:
每次我使用ScheduledThreadPoolExecutor
tomcat 都无法在取消部署/关闭/重启时关闭池线程,从而导致可能的内存泄漏(应该没问题,因为 tomcat 无法关闭它们, 但在它杀死它们之后,所以没问题,但客户不允许它...),而其他服务器工作得很好...
事实上,我创建了一个核心大小为 25 的 ScheduledThreadPoolExecutor,然后将其关闭(没有任何运行或计划)并且 tomcat 仍然无法清理池线程。
所以我的解决方案是在等待补丁时使用计时器...(它发生在 tomcat 6.0 和 jdk 1.5.0_22 上)
关于java - 使用tomcat可能发生内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3819817/