La gestion des exceptions de Java ExecutorService tâches
Je suis en train d'utiliser Java ThreadPoolExecutor
de la classe à exécuter un grand nombre de poids lourds tâches avec un nombre fixe de threads. Chacune de ces tâches a de nombreux endroits au cours de laquelle il peut échouer à cause des exceptions.
J'ai sous-classé ThreadPoolExecutor
et j'ai remplacé la afterExecute
méthode qui est censée fournir toutes les exceptions rencontrées pendant l'exécution de la tâche. Cependant, je n'arrive pas à le faire fonctionner.
Par exemple:
public class ThreadPoolErrors extends ThreadPoolExecutor {
public ThreadPoolErrors() {
super( 1, //core threads
1, //max threads
1, //timeout
TimeUnit.MINUTES, //timeout units
new LinkedBlockingQueue<Runnable>() //work queue
);
}
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if(t != null) {
System.out.println("Got an error: " + t);
} else {
System.out.println("Everything's fine--situation normal!");
}
}
public static void main( String [] args) {
ThreadPoolErrors threadPool = new ThreadPoolErrors();
threadPool.submit(
new Runnable() {
public void run() {
throw new RuntimeException("Ouch! Got an error.");
}
}
);
threadPool.shutdown();
}
}
La sortie de ce programme est "Tout va bien--situation normale!" même si la seule Praticable soumis pool de threads, déclenche une exception. La moindre idée de ce qui se passe ici?
Merci!
Vous devez vous connecter pour publier un commentaire.
De la docs:
Lorsque vous soumettez un Exécutable, il va avoir enveloppé dans un Avenir.
Votre afterExecute devrait être quelque chose comme ceci:
AVERTISSEMENT: Il convient de noter que cette solution permettra de bloquer le thread appelant.
Si vous souhaitez traiter les exceptions levées par la tâche, il est généralement préférable d'utiliser des
Callable
plutôt queRunnable
.Callable.call()
est autorisé à jeter checked exceptions, et ceux-ci sont renvoyés vers le thread appelant:Si
Callable.call()
déclenche une exception, ce sera enveloppé dans unExecutionException
et jeté parFuture.get()
.C'est probablement beaucoup préférable de sous-classement
ThreadPoolExecutor
. Il vous donne également la possibilité de re-présenter la tâche si l'exception est recouvrable d'un.future.get()
ou sa version surchargée est appelée.L'explication de ce comportement est droit dans le javadoc pour afterExecute:
Je suis autour en les enveloppant de l'exécutable fourni soumis à l'exécuteur testamentaire.
whenComplete()
méthode deCompletableFuture
.Je suis en utilisant
VerboseRunnable
classe de jcabi-journal, qui avale toutes les exceptions et les journaux eux. Très pratique, par exemple:Une autre solution serait d'utiliser la ManagedTask et ManagedTaskListener.
Vous avez besoin d'un Appelable ou Praticable qui implémente l'interface ManagedTask.
La méthode
getManagedTaskListener
retourne l'instance que vous souhaitez.Et vous mettre en ManagedTaskListener la
taskDone
méthode:Plus de détails sur gérées tâche du cycle de vie et l'auditeur.
Si vous souhaitez suivre l'exécution de la tâche, vous pouvez spin 1 ou 2 fils (peut-être plus en fonction de la charge) et les utiliser pour prendre des tâches à partir d'un ExecutionCompletionService wrapper.
Si votre
ExecutorService
provient d'une source externe (j'. e. il n'est pas possible à la sous-classeThreadPoolExecutor
et remplacerafterExecute()
), vous pouvez utiliser un proxy dynamique pour obtenir le comportement souhaité:C'est à cause de
AbstractExecutorService :: submit
est l'emballage de votrerunnable
enRunnableFuture
(mais rien deFutureTask
) comme ci-dessousPuis
execute
il passe àWorker
etWorker.run()
appellera ci-dessous.Cela fonctionne
Il va créer un Exécuteur testamentaire avec un seul fil, que vous pouvez obtenir un grand nombre de tâches; et à attendre de l'actuel à la fin d'exécution à commencer par la prochaine
En cas de uncaugth d'erreur ou d'exception la uncaughtExceptionHandler attraper
Au lieu de sous-classement ThreadPoolExecutor, je voudrais lui offrir un ThreadFactory instance qui crée de nouveaux Threads et leur offre une UncaughtExceptionHandler