На этот вопрос уже есть ответы здесь :
Закрыто 4 года назад .
У меня есть файл 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 будет отключен, и отменить мой таймер?
Какие еще решения я могу использовать для решения этой проблемы?
Спасибо!
ОБНОВЛЕНИЕ
Я изменил свой код на следующий, основываясь на поиске и ответе 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, это правильно?
Что мне еще нужно сделать?
Спасибо!
ОБНОВЛЕНИЕ
Не работает. Я поместил оператор журнала в метод contextDestroyed (), после того как я выключил Tomcat, в файле журнала будет только следующее:
PowderGodAppWebService -> [07 февраля 2012 16:09:46 PM] INFO (PowderGodAppWebService.java:45) :: СЕРВЕР DETECT TOMCAT ВЫКЛЮЧАЕТСЯ
PowderGodAppWebService -> [7 февраля 2012 г., 16:09:46] INFO (PowderGodAppWebService.java:46) :: ОТМЕНА ЗАДАЧИ И ТАЙМЕРА
ОТМЕНА ЗАВЕРШЕНИЯ отсутствует.
Я также проверил запущенные процессы (я не эксперт по Linux, поэтому я использую только Mac Activity Monitor.
Убедитесь, что не запущен ни один Java-процесс.
Запустите Tomcat, обратите внимание на PID этого java-процесса
Остановить Tomcat
Обнаружено, что процесс Tomcat отсутствует
Запустите Tomcat, обратите внимание на PID этого Java-процесса
Разверните мой военный файл
Пример процесса, см. [Timer-0] thread is there
Завершение работы Tomcat
Обнаружено, что процесс все еще существует
Пример процесса
См. [Таймер-0] все еще существует
ИСПРАВЛЕНО
Я изменил свой код на parserTimer = new Timer (true);
, чтобы мой таймер работал как поток демона, потому что contextDestroyed ()
вызывается после фактического завершения работы Tomcat.
«Все сервлеты и фильтры будут уничтожены раньше любого ServletContextListeners уведомляются об уничтожении контекста. "
http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContextListener.html