J'ai un fil de discussion de longue date qui effectue des tâches de maintenance. L'échec du thread est difficile à détecter étant donné que le système ne sera pas immédiatement affecté. Je veux m'assurer que ce fil ne meurt jamais. Je comprends que tant que le code attrape tout (Throwable), il ne mourra jamais. Voici l'exemple de code:
while (true) { try { // house keeping logic } catch (Throwable t) { // do not do anything } }
Ma compréhension est-elle correcte? Existe-t-il un meilleur moyen d'héberger des tâches d'arrière-plan de longue durée? Je sais que ScheduledExecutorService peut planifier des tâches périodiquement, mais si la tâche doit continuer à vérifier certaines ressources, il est probablement plus efficace de simplement tout mettre dans une boucle while.
3 Réponses :
Si la logique de gestion inclut certaines tâches qui pourraient être classées comme des tâches périodiques (par exemple, vérifiez la connectivité à un service une fois toutes les 20 secondes), alors vous feriez mieux d'utiliser TimerTask
Quelques exemple pourraient être utiles .
Si quelque chose (autre chose que MOO) se produit dans la TimerTask, cela n'affectera pas le minuteur responsable de la planification des tâches.
Quelques points:
Je recommande fortement d'utiliser ScheduledExecutorService
ou une autre fonctionnalité équivalente qui peut être fournie par tous les outils ou framework que vous utilisez (par exemple @Scheduled
au printemps). Il y a beaucoup de considérations dans ces situations qui ne sont pas immédiatement évidentes, et une bibliothèque bien établie et maintenue les traitera.
Deuxièmement, il est rare d'interroger les changements de cette manière sans délai. Un scénario typique peut vous obliger, par exemple, à fermer des connexions avec des machines qui n'ont pas répondu en 1 minute. Pour ce type de boucle, vous n'avez pas besoin de vérifier constamment, comme le fera la boucle ci-dessus. À tout le moins, vous devriez inclure un appel à Thread.sleep ()
pour éviter une utilisation excessive des ressources. (C'est un autre problème que ScheduledExecutorService
traite très bien).
Enfin, vous devriez inclure un moyen de quitter correctement la boucle lorsque votre application se termine. Un simple boolean running = true;
sur la classe suffirait, et vous changez ensuite votre boucle en: while (running) {...}
. Lorsque vous souhaitez quitter, définissez simplement running = false;
et votre boucle se fermera.
attraper tous les Throwable
ne capturera que les exceptions vérifiées Hein ?!
Mon erreur, clairement tard dans la nuit. Je modifierai ma réponse
Vous ne pouvez pas garantir un thread de longue durée. Cependant, vous pouvez avoir une logique de réapparition si quelque chose ne va pas avec votre thread.
Ce que vous pouvez faire est d'avoir un observateur qui vérifiera si le thread s'exécute toutes les x minutes.
Veuillez noter, l'observateur échouera si JVM est arrêté ou en panne. Si vous souhaitez redémarrer le thread même si JVM s'arrête, vous devez disposer d'une surveillance externe. Pour cela, vous pouvez utiliser des outils tels que supervisord.
public class LongRunningThread extends Thread { private volatile boolean IS_RUNNING = true; @Override public void run() { while (IS_RUNNING) { try { // actions this.houseKeep(); } catch (Exception e) { } } } private void houseKeep() { // housekeeping logic here } } class ThreadWatcher { private Thread threadToBeWatched; public ThreadWatcher(Thread threadToBeWatched) { this.threadToBeWatched = threadToBeWatched; } @Scheduled(cron = "*/1 * * * *") public void checkStatus() { if (!threadToBeWatched.isAlive()) { // Logic to restart the thread. } } }
p>
Le thread mourra avec la JVM entière dans quelques cas (par exemple
OutOfMemoryError
); il n'y a pas de processus immortel. Cela dépend de la ressource, mais mettre tout dans une bouclewhile
n'est certainement pas la manière la plus efficace.Dans quel type d'application ce fil est-il exécuté?