Java Exécuteurs: comment puis-je arrêter soumis tâches?
J'ai soumis une tâche à l'aide de exécuteurs testamentaires et j'en ai besoin pour s'arrêter après un certain temps (par exemple 5 minutes). J'ai essayé de faire comme ceci:
for (Future<?> fut : e.invokeAll(tasks, 300, TimeUnit.SECONDS)) {
try {
fut.get();
} catch (CancellationException ex) {
fut.cancel(true);
tasks.clear();
} catch(ExecutionException ex){
ex.printStackTrace(); //FIXME: gestita con printstack
}
}
Mais j'ai toujours une erreur: je partage un Vecteur qui doit être modifié par les tâches et ensuite lu par un fil, et même si j'ai arrêter toutes les la tâche, si le délai d'attente se produit-je obtenir:
Exception in thread "Thread-1" java.util.ConcurrentModificationException
Est-il quelque chose de mal? Comment puis-je arrêter les tâches soumises qui travaillent encore au bout de 5 minutes?
Di Fazio: j'ai formaté le code et ajout d'une accolade fermante, veuillez vérifier l'exactitude.
Merci, je suis désolé pour la mauvaise mise en forme.
Merci, je suis désolé pour la mauvaise mise en forme.
OriginalL'auteur Raffo | 2009-09-13
Vous devez vous connecter pour publier un commentaire.
Juste parce que vous appelez
cancel()
surFuture
ne veut pas dire que la tâche s'arrête automatiquement. Vous avez à faire un peu de travail au sein de la tâche pour s'assurer qu'il va s'arrêter:cancel(true)
de sorte qu'une interruption est envoyée à la tâche.InterruptedException
. Si une fonction dans votre tâche jette unInterruptedException
, assurez-vous de fermer correctement dès que possible après la capture de l'exception.Thread.currentThread().isInterrupted()
si la tâche ne calcul continu.Par exemple:
Aussi, comme d'autres postes ont mentionné:
ConcurrentModificationException
peut être levée même si l'aide de l'thread-safeVector
classe, parce que les itérateurs vous obtenez à partir deVector
ne sont pas thread-safe, et donc doivent être synchronisés. Avancés pour de la boucle utilise les itérateurs, donc attention:Tout d'abord, l'appel de l'avenir.annuler(vrai) ne fait absolument rien. Le contrat de invokeAll indique qu'il va annuler les tâches avant de rentrer, et la mise en œuvre utilise un bloc final pour s'assurer qu'il. Deuxièmement, il ne faut jamais appeler Fil.interrompu(), cela efface l'interruption de l'état du thread. La plupart des implémentations souhaitez utiliser Thread.isInterrupted(). La désactivation de l'indicateur doit être examiné de près. Troisièmement, il n'a pas à gérer la InterruptedException à moins qu'il soit de blocage à l'aide de méthodes telles que l'acquisition de verrou, puis le compilateur s'assure qu'il est. Le FutureTask va attraper les exceptions.
Bender: Vous avez raison: à l'avenir.annuler(vrai) ne fait rien, testé par moi-même. Mais je n'ai pas compris ce que tu pense que je devrais faire..
Bender: Vous avez absolument raison sur Fil.interrompu() par rapport au Fil.isInterrupted(). Le réel de la syntaxe serait Thread.currentThread().isInterrupted().
Bender: Vous n'AVEZ pas à attraper InterruptedException, mais si vous souhaitez gérer le nettoyage avant la sortie de la méthode, vous pouvez attraper & renvoyer.
OriginalL'auteur Matt Fichman
La
ConcurrentModificationException
est à venir à partir de votre appel àtasks.clear()
pendant que votre Exceutors est une itération sur votretasks
Vector
. Ce que vous pouvez essayer de faire est d'appelershutdownNow()
sur votre ExecutorServiceOriginalL'auteur akf
Le cas le plus fréquent pour
ConcurrentModificationException
, c'est quand levector
est en cours de modification dans le même temps, comme c'est itérée. Souvent, ce sera fait dans un seul thread. Vous avez besoin de placer un verrou sur laVector
pour l'ensemble de l'itération (et attention à ne pas l'impasse).OriginalL'auteur Tom Hawtin - tackline
fut.get() est un appel bloquant, même après le délai d'attente, vous bloquera jusqu'à ce que la tâche est accomplie. Si vous souhaitez terminer le plus proche à 5 minutes de marque que possible, vous avez besoin de vérifier le drapeau d'interruption, je viens vous recommandons de le faire à l'aide du Fil.isInterrupted() méthode qui préserve l'interruption de l'etat. Si vous voulez arrêter immédiatement et n'ont pas besoin de nettoyer n'importe quel état, puis lever une exception qui sera pris par l'Avenir et indiqué comme un ExecutionException.
fut.annuler(vrai) ne fait rien comme les invokeAll() la méthode a déjà fait pour vous.
Sauf si vous utilisez les "tâches" de la Collection de quelque part d'autre, vous n'avez probablement pas besoin d'appeler clear() sur celui-ci. Cela ne va pas être la source de votre problème depuis le invokeAll() la méthode est fait avec la Liste au moment de l'appel à clear(). Mais, si vous avez besoin de commencer à constituer une liste de tâches à exécuter, je vous suggère de former une nouvelle Liste de tâches, de ne pas utiliser une vieille Liste de Tâches nouvelles.
Malheureusement, je n'ai pas de réponse à votre problème. Je ne vois pas de suffisamment d'informations pour établir un diagnostic. Rien dans l'extrait de code que vous avez fourni indique une mauvaise (seulement inutile) l'utilisation de la bibliothèque de classes/méthodes. Peut-être si vous avez inclus un full stack trace, au lieu de la ligne d'erreur.
OriginalL'auteur Tim Bender
Mettre le
fut.cancel(true);
dans le bloc finallyfinally
bloc, non?OriginalL'auteur clinton