java tomcat定时器,关闭tomcat时停止计划的计时器

I have a WAR file deployed to Tomcat server, one of the class will get called at start up time, then the init() method will schedule a timer to fire every 5 hours to perform some tasks.

My init() code looks like this:

public void init()

{

TimerTask parserTimerTask = new TimerTask() {

@Override

public void run() {

XmlParser.parsePage();

}

};

Timer parserTimer = new Timer();

parserTimer.scheduleAtFixedRate(parserTimerTask, 0, PERIOD);

}

My application runs without problem, but when I shutdown the Tomcat using /etc/init.d/tomcat7 stop, then I check the log (catalina.out) it has a entry like this:

SEVERE: The web application [/MyApplication] appears to have started a thread named [Timer-0] but has failed to stop it. This is very likely to create a memory leak.

I understand this is caused by me schedule the timer, but my question is:

I didn't set setDeamon to true, so shouldn't the timer prevent Tomcat from shutting down, rather than left running?

Can I, in my application, detect Tomcat is going to be shutdown and cancel my timer?

What are the other solutions I can use to take care of this issue?

Thanks!

UPDATE

I changed my code to the following based on some search and DaveHowes's answer.

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) {

}

Now my new question:

I cancel TimerTask first then Timer, is this correct?

Are there other thing I should do?

Thanks!

UPDATE

It doesn't work. I put some logging statement in the contextDestroyed() method, after I shutdown Tomcat, the log file only has the following:

PowderGodAppWebService -> [07 Feb 2012 04:09:46 PM] INFO (PowderGodAppWebService.java:45):: DETECT TOMCAT SERVER IS GOING TO SHUT DOWN

PowderGodAppWebService -> [07 Feb 2012 04:09:46 PM] INFO (PowderGodAppWebService.java:46):: CANCEL TIMER TASK AND TIMER

CANCELING COMPLETE is not there.

I also checked processes that are running (I'm not a Linux expert so I just use Mac's Activity Monitor.

Make sure no java process is running

Start Tomcat, note the PID of that java process

Stop Tomcat

Found the Tomcat process is gone

Start Tomcat, note the PID of that java process

Deploy my war file

Sample the process, see [Timer-0] thread is there

Shutdown Tomcat

Found that the process is still there

Sample the process

See [Timer-0] is still there

FIXED

I changed my code to parserTimer = new Timer(true); so that my timer runs as a daemon thread because the contextDestroyed() gets called after Tomcat actually shuts down.

"All servlets and filters will have been destroyed before any ServletContextListeners are notified of context destruction."

解决方案

Do not use Timer in an Java EE environment! If the task throws a runtime exception, then the whole Timer is killed and won't run anymore. You basically needs to restart the whole server to get it to run again. Also, it is sensitive to changes in the system clock.

Use ScheduledExecutorService instead. It's not sensitive to exceptions thrown in tasks nor to changes in system clock. You can shutdown it by its shutdownNow() method.

Here's an example of how the entire ServletContextListener implementation can look like (note: no registration in web.xml required thanks to the new @WebListener annotation):

@WebListener

public class BackgroundJobManager implements ServletContextListener {

private ScheduledExecutorService scheduler;

@Override

public void contextInitialized(ServletContextEvent event) {

scheduler = Executors.newSingleThreadScheduledExecutor();

scheduler.scheduleAtFixedRate(new YourParsingJob(), 0, 5, TimeUnit.HOUR);

}

@Override

public void contextDestroyed(ServletContextEvent event) {

scheduler.shutdownNow();

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值