Java: Set timeout pour les threads dans un pool de threads
Je veux définir les délais pour les threads qui sont exécutés à l'intérieur d'un pool de threads. Pour le moment j'ai code suivant:
ExecutorService executor = Executors.newFixedThreadPool(8);
for(List<String> l: partition) {
Runnable worker = new WorkerThread(l);
executor.execute(worker);
}
executor.shutdown();
while (!executor.isTerminated()) {
}
Le code divise une grande liste d'objets dans des sous-listes et les processus de ces sous-liste à l'intérieur d'un fils. Mais ce n'est pas le point.
Je veux donner à chaque seul thread dans le pool de threads d'un délai d'attente. Pour un seul thread à la piscine, j'ai trouvé la solution suivante:
Future<?> future = null;
for (List<String> l : partition) {
Runnable worker = new WorkerThread(l);
future = executor.submit(worker);
}
try {
System.out.println("Started..");
System.out.println(future.get(3, TimeUnit.SECONDS));
System.out.println("Finished!");
} catch (TimeoutException e) {
System.out.println("Terminated!");
}
Mais ce ne serait pas travailler pour plus d'un thread. Peut-être que je dois mettre chaque thread dans un List<Future>
liste et de parcourir cette liste et définir un délai d'attente pour chaque future
objet?
Des suggestions?
MODIFIER APRÈS l'UTILISATION de CountDownLatch:
CountDownLatch doneSignal = new CountDownLatch(partition.size());
List<Future<?>> tasks = new ArrayList<Future<?>>();
ExecutorService executor = Executors.newFixedThreadPool(8);
for (List<String> l : partition) {
Runnable worker = new WorkerThread(l);
tasks.add(executor.submit(doneSignal, worker));
}
doneSignal.await(1, TimeUnit.SECONDS);
if (doneSignal.getCount() > 0) {
for (Future<?> fut : tasks) {
if (!fut.isDone()) {
System.out.println("Task " + fut + " has not finshed!");
//fut.cancel(true) Maybe we can interrupt a thread this way?!
}
}
}
Fonctionne bien jusqu'à présent.
Alors, la prochaine question est de savoir comment interrompre un thread qui est expiré? J'essaie fut.cancel(true)
et ajouter la suite de construire dans certaines critiques les boucles dans le thread de travail:
if(Thread.interrupted()) {
System.out.println("!!Thread -> " + Thread.currentThread().getName() + " INTERRUPTED!!");
return;
}
De sorte que le thread de travail est "tué" après l'expiration du délai. Est-ce une bonne solution?
En outre: Est-il possible d'obtenir le nom du thread qui a expiré au cours de la Future
interface? Pour le moment j'ai l'impression de le nom dans la si la condition de la Thread.interrupted()
construire.
Merci pour l'aide!
Ce qui concerne
S'il vous plaît ne pense pas que sur les fils de cette façon. Il y a quelque chose qui est fait, et que vous voulez un délai d'attente si il faut plus d'une certaine quantité de temps. Ce n'est pas tout ce thread pourrait arriver à faire ce travail, c'est le . Peut-être que les deux fils sont de la coopération sur le travail. Peut-être pas de thread est en train de travailler sur ce travail à l'époque. Mais c'est le vous voulez arrêter ou de délai d'attente ou que ce soit, de ne pas le fil ou les fils qui pourraient ou ne pourraient pas arriver à travailler sur elle. Ce subtil vue décalage est important de penser correctement sur les threads de sorte que vous vous retrouvez avec de bonnes conceptions.
bon point cependant, il peut y avoir des situations n'étaient que des travaux sont complètement indépendants l'un de l'autre. Je ne sais pas si l'OP en fait si à ce sujet, mais il semble que c'est le cas ici.
Il n'est pas sur la relation entre les œuvres les unes aux autres. C'est à propos de la notion de "travail" (la chose qui doit être fait) étant distinct de la thread(s) qui le font. Si le travail est en attente pour quelque chose, pas de fil peut être associé avec lui. Si le travail peut être fait simultanément, plusieurs threads peuvent coopérer pour faire. Lorsque vous êtes en attente pour l'exécution de certains travaux, vous ne devriez pas penser à ce fil ou des fils, le cas échéant, de travailler sur elle.
OriginalL'auteur sk2212 | 2013-01-09
Vous devez vous connecter pour publier un commentaire.
Avez-vous vu cela? ExecutorService.invokeAll
Il doit être exactement ce que vous voulez: Invoquer un ensemble de travailleurs et leur délai d'attente en cas de prise trop longtemps.
MODIFIER après le commentaire - (nouvelle idée):
Vous pouvez utiliser un CountDownLatch à attendre pour les tâches de finition ET de délai d'attente par
await(long timeout, TimeUnit unit)
!Ensuite, vous pouvez même faire un shutdownNow et de voir les tâches qui ont pris trop de temps ...
EDIT 2:
Pour le rendre plus clair:
await
avec délai sur ledit loquet.b) si non, boucle les contrats à Terme et vérifier leur
isDone
. Vous n'avez pas à appeler de l'arrêt sur le ExecutorService.Remarque: les Travailleurs peuvent finir dans l'intervalle entre le délai d'attente et l'appel de leur Avenir isDone().
Pas nécessairement. Vous pouvez toujours parcourir les contrats à terme d'un sondage isDone() ou appeler get() sur chaque Futur ou vous pouvez faire usage d'un docs.oracle.com/javase/7/docs/api/java/util/concurrent/... je considère que le dernier de la "plus belle".
Ahh, ok très bon. "CountDownLatch" est très joli. Vous dites (dans votre "modifier" les lignes) que je peux courir shutdownNow après l'appel de l'attendent. Donc, la méthode shutdownNow va annuler tous les threads qui sont toujours en cours d'exécution en raison de la temporisation? C'est ma prochaine question car je ne trouve aucun moyen avec invokeAll pour savoir quels sujets sont les "violé" le délai d'attente. Peut-être qu'avec la nouvelle approche, il est possible?
Seul un léger changement. Vous pourrez appeler attendent sur le CountDownLatch exemple avec un délai d'attente. Cet appel sera bloqué jusqu'à ce que le délai d'attente frappe ou le loquet est à 0. Après cela, vous pouvez shutdownNow, qui renvoie une liste de ... ahhh viens de lire que c'est seulement les unstarted tâches qui sont retournés par shutdownNow. Mais vous pouvez toujours parcourir les contrats à Terme et demandez-leur s'ils sont fait 🙂
Ok, mais également si je itérer sur les contrats à Terme et leur demander si ils sont en fait je l'ai d'appel de l'arrêt() ou shutdownNow(). Pour le moment, je reçois un "java.util.de façon concomitante.CancellationException" quand vous faites cela, sans faire appel à l'arrêt(): List<Avenir<String>> liste = exécuteur testamentaire.invokeAll(tâches 1, TimeUnit.SECONDES); pour les(Futurs<String> fut : liste){ if(fut.isDone()) { System..println("Tâche" + fut.get() + " est terminé."); } } Le Futur est de retourner une chaîne de caractères contenant le nom du Thread. EDIT: SANS l'AIDE de "CountDownLatch"
OriginalL'auteur Fildor