0
votes

Comment s'assurer qu'un thread Java de longue durée ne meurt jamais

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.


2 commentaires

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 boucle while n'est certainement pas la manière la plus efficace.


Dans quel type d'application ce fil est-il exécuté?


3 Réponses :


0
votes

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.


0 commentaires

-1
votes

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.


2 commentaires

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



1
votes

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>


0 commentaires