Ho un file WAR distribuito sul server Tomcat, una delle classi verrà richiamata all'avvio, quindi il metodo init() pianificherà un timer che si attiva ogni 5 ore per eseguire alcune attività .Arresta il timer programmato all'arresto del telefono tomcat
codicemio init() è simile al seguente:
public void init()
{
TimerTask parserTimerTask = new TimerTask() {
@Override
public void run() {
XmlParser.parsePage();
}
};
Timer parserTimer = new Timer();
parserTimer.scheduleAtFixedRate(parserTimerTask, 0, PERIOD);
}
La mia applicazione funziona senza problemi, ma quando ho spegnere il Tomcat utilizzando /etc/init.d/tomcat7 fermo, poi controllare il registro (catalina.out) ha una voce come questa:
SEVERE: L'applicazione Web [/ MyApplication] sembra aver avviato un thread chiamato [Timer-0] ma non è riuscito a fermarlo. È molto probabile che questo crei una perdita di memoria.
posso capire che questo è causato da me programmare il timer, ma la mia domanda è:
- non ho impostato
setDeamon
su true, quindi non dovrebbe impedire che il timer Tomcat di arrestare, piuttosto che lasciato in esecuzione? - Posso, nella mia applicazione, rilevare che Tomcat sta per essere spento e annullare il mio timer?
- Quali sono le altre soluzioni che posso utilizzare per risolvere questo problema?
Grazie!
UPDATE
ho cambiato il mio codice di seguito sulla base di alcuni di ricerca e la risposta di 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) {
}
Ora la mia nuova domanda:
- annullo TimerTask prima quindi Timer, è corretto?
- Ci sono altre cose che dovrei fare?
Grazie!
UPDATE
Non funziona. Inserisco alcune istruzioni di registrazione nel metodo contextDestroyed(), dopo aver spento Tomcat, il file di registro ha solo il seguente:
PowderGodAppWebService -> [07 Feb 2012 04:09:46 PM] INFO (PowderGodAppWebService.java:45) :: DETECT TOMCAT server sta per CHIUDERE PowderGodAppWebService -> [7 Feb 2012 16:09:46] INFO (PowderGodAppWebService.java:46) :: CANCELLA TIMER COMPITO E TIMER
Annullamento COMPLETO è non là.
Ho controllato anche i processi in esecuzione (non sono un esperto di Linux, quindi utilizzo semplicemente Activity Monitor di Mac.
- Assicurarsi che nessun processo di Java è in esecuzione
- Avviare Tomcat, si noti il PID di quel processo java
- arresto Tomcat
- Trovato il processo di Tomcat è andato
- Avviare Tomcat, si noti il PID quel processo java
- Distribuire il mio file di guerra
- campione del processo, si veda [Timer-0] filo c'è
- Shutdown Tomcat
- Trovato che il processo è ancora lì
- Campione del processo
- Sede [Timer-0] è ancora lì
FISSO
ho cambiato il mio codice per parserTimer = new Timer(true);
in modo che il mio timer venga eseguito come thread daemon perché contextDestroyed()
viene chiamato dopo l'arresto effettivo di Tomcat.
"Tutti i servlet e i filtri saranno stati distrutti prima che qualsiasi ServletContextListeners venga informato della distruzione del contesto."
http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContextListener.html
Non dovrebbe quegli annulli essere in contextDestroyed()? – DaveH
Sì ... immagino sia ora di andare a letto, grazie per avermelo fatto notare! –
TimerTask # cancel non interromperà l'attività se è attualmente in esecuzione - si accerterà che non verrà mai più eseguita - ma a parte questo, direi che staresti bene con quello – DaveH