У меня есть файл 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);
}
Мое приложение работает без проблем, но когда я завершаю Tomcat с помощью /etc/init.d/tomcat7 stop, тогда я проверяю журнал (catalina.out), у него есть запись вроде этого:
SEVERE: веб-приложение [/MyApplication], похоже, запустило поток с именем [Timer-0], но не остановило его. Вероятно, это приведет к утечке памяти.
Я понимаю, что это вызвано тем, что я расписал таймер, но мой вопрос:
- Я не установил
setDeamon
в значение true, поэтому не следует ли отключать таймер Tomcat, а не работать? - Могу ли я в своем приложении обнаружить, что Tomcat будет отключен и отменит мой таймер?
- Каковы другие решения, которые я могу использовать для решения этой проблемы?
Спасибо!
UPDATE
Я изменил свой код на следующий, основанный на некотором поиске и ответе 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) {
}
Теперь мой новый вопрос:
- Я отменяю TimerTask сначала, а затем Timer, это правильно?
- Есть ли еще что я должен делать?
Спасибо!
UPDATE
Это не работает. Я положил некоторый оператор регистрации в метод contextDestroyed(), после того, как я завершаю Tomcat, файл журнала имеет только следующее:
PowderGodAppWebService → [07 Фев 2012 04:09:46 PM] INFO (PowderGodAppWebService.java:45):: DETECT TOMCAT SERVER НАХОДИТСЯ В ОТНОШЕНИИ PowderGodAppWebService → [07.02.2012 04:09:46] INFO (PowderGodAppWebService.java:46):: ОТМЕНА ТАЙМЕРА ТАЙНА И ТАЙМЕР
ОТМЕНА ПОЛНОГО не существует.
Я также проверил процессы, которые выполняются (я не эксперт по Linux, поэтому просто использую монитор активности Mac.
- Убедитесь, что java-процесс не запущен.
- Запустите Tomcat, обратите внимание на PID этого java-процесса.
- Остановить Tomcat
- Найден процесс Tomcat не работает
- Запустите Tomcat, обратите внимание на PID этого java-процесса.
- Разверните мой файл войны
- Пример процесса, см. [Timer-0] thread есть
- Shutdown Tomcat
- Установлено, что процесс все еще существует
- Пример процесса
- См. [Timer-0] все еще существует
Fixed
Я изменил свой код на parserTimer = new Timer(true);
, чтобы мой таймер работал как поток демона, потому что вызов contextDestroyed()
вызывается после того, как Tomcat фактически завершает работу.
"Все сервлеты и фильтры будут уничтожены до того, как будут обнаружены сведения об уничтожении контекста ServletContextListeners.
http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContextListener.html