关闭 tomcat 时停止计划的计时器
我有一个WAR文件部署到Tomcat服务器,其中一个类将在启动时被调用,然后init()方法将安排一个计时器,每5小时触发一次以执行一些任务。
我的 init() 代码如下所示:
public void init()
{
TimerTask parserTimerTask = new TimerTask() {
@Override
public void run() {
XmlParser.parsePage();
}
};
Timer parserTimer = new Timer();
parserTimer.scheduleAtFixedRate(parserTimerTask, 0, PERIOD);
}
我的应用程序运行没有问题,但是当我使用/etc/init.d/tomcat7 stop关闭Tomcat时,我检查了日志(catalina.out),它有一个这样的条目:
严重:Web 应用程序 [/MyApplication] 似乎启动了一个名为 [Timer-0] 的线程,但未能停止它。这很可能会造成内存泄漏。
我知道这是由我安排计时器引起的,但我的问题是:
- 我没有设置为 true,所以计时器不应该阻止 Tomcat 关闭,而不是继续运行吗?
setDeamon
- 在我的应用程序中,我可以检测到Tomcat将要关闭并取消我的计时器吗?
- 我可以使用哪些其他解决方案来解决此问题?
谢谢!
更新
我根据一些搜索和DaveHowes的答案将代码更改为以下内容。
Timer parserTimer;
TimerTask parserTimerTask;
public void init()
{
parserTimerTask = new TimerTask() {
@Override
public void run() {
XmlParser.parsePage();
}
};
parserTimer = new Timer();
parserTimer.scheduleAtFixedRate(parserTimerTask, 0, PERIOD);
}
@Override
public void contextDestroyed(ServletContextEvent arg0) {
Logger logger = Logger.getRootLogger();
logger.info("DETECT TOMCAT SERVER IS GOING TO SHUT DOWN");
logger.info("CANCEL TIMER TASK AND TIMER");
otsParserTimerTask.cancel();
otsParserTimer.cancel();
logger.info("CANCELING COMPLETE");
}
@Override
public void contextInitialized(ServletContextEvent arg0) {
}
现在我的新问题:
- 我先取消计时器任务,然后取消计时器,这是正确的吗?
- 我还有其他应该做的事情吗?
谢谢!
更新
它不起作用。我在 contextDestroyed() 方法中放置了一些日志记录语句,在我关闭 Tomcat 之后,日志文件只有以下内容:
PowderGodAppWebService -> [07 Feb 2012 04:09:46 PM] INFO (PowderGodAppWebService.java:45):: DETECT TOMCAT SERVER IS WILL OFF OFF POWDERGodAppWebService -> [07 Feb 2012 04:09:46 PM] INFO (PowderGodAppWebService.java:46):: CANCEL TIMER TASK AND TIMER
取消完成不存在。
我还检查了正在运行的进程(我不是Linux专家,所以我只使用Mac的活动监视器。
- 确保没有 Java 进程正在运行
- 启动Tomcat,注意该java进程的PID
- 停止雄猫
- 发现雄猫进程不见了
- 启动Tomcat,注意该java进程的PID
- 部署我的战争文件
- 对流程进行采样,请参阅 [Timer-0] 线程是否存在
- 关闭雄猫
- 发现流程仍然存在
- 对流程进行采样
- 查看 [Timer-0] 是否仍然存在
固定
我将代码更改为,以便我的计时器作为守护程序线程运行,因为在Tomcat实际关闭后调用了。parserTimer = new Timer(true);
contextDestroyed()
“所有 Servlet 和过滤器都将在任何 ServletContextListener 被通知上下文破坏之前被销毁。
http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContextListener.html