我正在使用struts和quartz框架来安排工作。它工作正常。
但是当我停止Tomcat(6.0.26)时,它会在控制台上抛出错误,如
“Web应用程序似乎已经启动了一个名为[.....]但未能阻止它的线程。这很可能会导致内存泄漏。
任何人都知道如何妥善处理......
目前我的struts config.xml如下所示:
<plug-in className="com.example.scheduler.SchedulerPlugin">
<set-property property="startOnLoad" value="true"/>
<set-property property="startupDelay" value="0"/>
</plug-in>
答案 0 :(得分:5)
确定的最好方法是发送一个SIGQUIT(kill -3)程序并分析输出以查看哪个线程仍在运行。
你的作业(在一个Quartz线程之上运行)很可能没有对关机信号作出反应并继续工作。对于长时间工作,您可以定期检查jobExecutionContext.getScheduler().isShutdown()
或将作业编程为InterruptableJob
并正确回应中断。
答案 1 :(得分:4)
您需要调用scheduler.shutdown(true)告诉Quartz等待任何正在进行的作业完成执行。
另外,一些tomcat用户报告说他们还需要在关闭调用后暂停该线程一秒左右,以便在tomcat尝试检测线程是否仍在运行之前允许其他线程cpu时间进行清理。
请参阅此处的讨论:http://forums.terracotta.org/forums/posts/list/3479.page
答案 2 :(得分:3)
这是jhouse答案的扩展。我无法将此代码放在评论中: - (。
具体来说,您需要在web.xml中添加ServletContextListener:
<listener>
<listener-class>org.whatever.MyListener</listener-class>
</listener>
然后在实现中,在contextDestroyed()方法的上下文中,睡眠10秒钟(1秒钟对我的应用程序来说已经不够了)。看起来应该是这样的:
public class MyListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent arg0) {}
/**
* @see ServletContextListener#contextDestroyed(ServletContextEvent)
*/
public void contextDestroyed(ServletContextEvent arg0) {
try {
// This can't use logging because it's (hopefully) been shut down by now.
System.out.println("Sleep for a bit so that we don't get any errors about Quartz threads not being shut down yet. ");
// For more info, see here: http://stackoverflow.com/questions/2730354/spring-scheduler-shutdown-error
Thread.sleep(10 * 1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
我没有必要调用调度程序关闭方法(很明显,他们已经在某个地方被调用了,也许&#39;因为我使用的是Spring)。我需要做的只是添加等待,然后它们都消失了(除了FileWatchdog Log4j线程和其他一些MySQL线程,但这些是不同的问题)。