Constamment annuler et recréer la minuterie, TimerTask en Java


Je sais que l'utilisation de Timer et TimerTask n'est plus la pratique acceptée actuelle (certains ont suggéré d'utiliser des threads, d'autres suggèrent d'utiliser ScheduledExecutorService ou ses variantes), donc cette question ne concerne pas tant les bonnes pratiques de programmation, mais la possibilité d'erreurs ou d'exceptions réelles.

Essentiellement, ce que j'ai est un servlet qui conserve un compteur en cours d'exécution (qui est un objet de calendrier statique) qui est incrémenté chaque seconde. Lorsqu'un délai spécifié est respecté (lorsque nous atteindre 10 minutes par défaut), je fais un appel de mon application à un serveur de temps NIST pour obtenir l'heure actuelle, que j'utilise ensuite pour réinitialiser mon compteur.

La même méthode définie par TimerTask qui incrémente le compteur (toutes les secondes) est également celle qui doit être mise en pause et re-planifiée chaque fois que je fais un appel à un serveur NIST (toutes les dix minutes). J'ai échoué à mettre en pause/annuler les objets Timer / TimerTask existants avant {[7] } l'appel du serveur NIST et la re-planification le TimerTask après l'appel.

Les exceptions qui en découlent sont décrites ici: Comment puis-je utiliser une minuterie en Java lorsque nécessaire pour définir et annuler plusieurs fois?

Il suffit de dire que ni TimerTask ni Timer ne peuvent être programmés plus d'une fois, même en utilisant purge() ou cancel (), qui semblent être seulement bons pour définir ces objets comme éligibles pour Java garbage collection.

L'utilisation de wait () et notify() a entraîné des exceptions de synchronisation que je n'ai malheureusement pas eu le temps de comprendre, donc mon expérience initiale avec le filetage a été un échec.

Ce que j'ai fini par faire est ceci:

secondTickerTask.cancel();
secondTicker.purge();
secondTicker.cancel();

secondTickerTask = null;
secondTicker = null;

Date newCurrentTime = getNistTimeFromFirstWorkingServer();

// Save new date to current time, reset second counter.
setCurrentTimeAndDeadline(newCurrentTime);
startSecondIncrementTimer(newCurrentTime);

secondTicker = new Timer();
secondTickerTask = new TimerTask(){
    public void run(){
        incrementCurrentTimeAndTestDeadline();
    }

J'ai exécuté ce code pendant la nuit plusieurs fois, à des intervalles de 10 minutes et 1 minute entre les appels du serveur NIST, et cela a fonctionné sans problème.

Donc, après ce long délai (merci pour votre patience), voici ma question: Étant obligé, pour le moment, d'utiliser le code que j'ai, y a-t-il des dommages qui pourraient résultat à long terme? Si je continue à créer de nouveaux objets TimerTask et Timer tout en annulant les anciens sur, disons, une période d'un mois, ou six mois, vais-je forcer le serveur à manquer de mémoire? La garbage collection de Java est-elle suffisamment robuste pour gérer ce type d'utilisation? Aucune autre effrayant chose?

Merci beaucoup pour votre temps, - Eli

Author: Community, 2013-11-07

1 answers

Java gérera très bien la création et l'abandon des tâches de minuterie. Vous devez vous assurer de supprimer toutes les références aux minuteries lorsque vous en avez terminé avec elles, ce qu'il semble que vous fassiez, puis lorsque le GC s'exécute, il nettoiera toutes les ordures que les minuteries ont introduites.

Vous êtes en sécurité.

Vous devez noter que, sur de longues périodes de temps, certains processus Java ont tendance à continuer à allouer de la mémoire jusqu'à ce qu'ils atteignent leur limite -Xmx. Cela ne signifie pas qu'il y est un problème (parce que cet espace sera réutilisé par le GC), mais cela signifie également que, si vous voulez qu'un processus Java de longue durée ait une empreinte relativement faible, vous ne devez pas spécifier un -Xmx beaucoup plus grand que ce dont vous avez réellement besoin.

 2
Author: rolfl, 2013-11-07 16:41:13