29 votes

Comment intercepter correctement les RuntimeExceptions des exécuteurs?

Dire que j'ai le code suivant:

ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(myRunnable);

Maintenant, si myRunnable jette un RuntimeExcpetion, comment puis-je rattraper? Un autre moyen serait d'approvisionnement mon propre ThreadFactory de la mise en œuvre d' newSingleThreadExecutor() et personnaliser uncaughtExceptionHandlers pour Threads qui en sont issus. Une autre façon serait pour envelopper myRunnable d'un local (anonyme) Runnable qui contient un try-catch -bloc. Peut-être il y a d'autres solutions similaires aussi. Mais... d'une certaine façon cela se sent sale, je pense qu'il ne devrait pas être si compliqué. Est-il une solution propre?

39voto

skaffman Points 197885

La solution de contournement propre consiste à utiliser ExecutorService.submit() au lieu de execute() . Cela vous renvoie un Future que vous pouvez utiliser pour récupérer le résultat ou l'exception de la tâche:

 ExecutorService executor = Executors.newSingleThreadExecutor();
Runnable task = new Runnable() {
  public void run() {
    throw new RuntimeException("foo");
  }
};

Future<?> future = executor.submit(task);
try {
  future.get();
} catch (ExecutionException e) {
  Exception rootException = e.getCause();
}
 

10voto

Brian Agnew Points 143181

Pourquoi ne pas appeler ExecutorService#submit(), obtenir l' Future de retour et de gérer des exceptions possibles à vous-même lors de l'appel d' Future#get() ?

5voto

Adamski Points 29884

skaffman est correct que l'utilisation d' submit est la plus propre approche. Une approche alternative consiste à sous-classe ThreadPoolExecutor et remplacer afterExecute(Runnable, Throwable). Si vous suivez cette approche, faites appel à execute(Runnable) plutôt que d' submit(Runnable) ou afterExecute ne sera pas invoquée.

Par la description de l'API:

Méthode appelée lors de l'achèvement de l'exécution de l'Exécutable. Cette la méthode est appelée par le thread exécuté la tâche. En cas de non-nulle, le Throwable est le uncaught RuntimeException ou Error qui a causé l'exécution de s'arrêter brutalement.

Remarque: Lorsque des actions sont enfermés dans des tâches (telles que FutureTask) soit explicitement ou par des méthodes telles que soumettre, ces objets de capture et maintenir calcul des exceptions, et de sorte qu'ils ne causent pas de brusque résiliation, et l'interne les exceptions sont pas passés à cette la méthode.

5voto

Aaron Digulla Points 143830

Décorez l'exécutable dans un autre exécutable qui intercepte les exceptions d'exécution et les gère:

 public class REHandler implements Runnable {
    Runnable delegate;
    public REHandler (Runnable delegate) {
        this.delegate = delegate;
    }
    public void run () {
        try {
            delegate.run ();
        } catch (RuntimeException e) {
            ... your fancy error handling here ...
        }
    }
}

executor.execute(new REHandler (myRunnable));
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X