8
votes

Communication entre Java Threads: Arrêtez toutes les filetages lorsque l'on finit sa tâche

J'ai n Les threads fonctionnant en parallèle et chacun d'entre eux fait une logique personnalisée. Cependant, mon exigence est que lorsque l'un des threads finit l'exécution, tous les autres threads doivent arrêter l'exécution et le retour.

Quel est le meilleur moyen de mettre en œuvre cela? J'ai pensé à cela en ayant une variable booléenne commune. Lorsque l'un des threads finit l'exécution, il fixera le booléen. Tous tous les threads lisent périodiquement cette variable et sortent si lorsqu'il est défini.

En outre, ma logique personnalisée est une boucle infinie et dès que je sais qu'un autre thread a fini d'exécution, je souhaite arrêter l'exécution après l'itération actuelle.

Quelle est la bonne façon de faire cela?


6 commentaires

Dupliqué possible de Communication inter thread en Java


Reproduire tous les autres fils de ce fil spécial !!!!


@ Andersr.Bystrup Je ne suis pas convaincu que c'est un bon double, cela ne répond pas vraiment à cette question.


Chaque fois que vous créez une nouvelle instance de thread, ajoutez ce fil à la liste mondiale des threads. Cette liste de threads agira comme piscine de fil. Si un thread arrête l'exécution. Vous bouclez la piscine et arrêtez chaque fil. C'est une solution assez simple, j'espère que cela vous aidera.


Dupliqué possible de Communication entre threads en Java: arrêter un fil si un autre thread a terminé


Qu'est-ce que vous faites exactement dans ces thread s, pourquoi n'attendent-ils pas quelque chose? Est-ce un calcul mathématique, par exemple Trouver un prime?


3 Réponses :


9
votes

Utilisez un exécutantservice et son .Invokeany () Méthode (Remarque: il y a aussi une version avec un délai d'attente).

du Javadoc:

Exécute les tâches données, renvoyant le résultat d'un qui s'est terminé avec succès (c'est-à-dire sans lancer une exception), le cas échéant.

Un que vous avez votre résultat, .Shutdown () l'exécuteur exécutif.

Voir le exécuteurs classe pour obtenir un exécuteur qui correspond à vos besoins.

Une autre solution est la ExecutorCletservice < / a> classe; Dans ce cas, vous devez .take () au lieu de .invokeany () , et devrait soumettre chaque tâche une par une. Et vous devez également conserver une référence à votre exécuttorservice car vous en avez besoin d'un autre argument et que vous devez l'arrêter également.

(Remarque: Si vous ne retournez pas de résultat, faites appelable << / code> void > instances)


3 commentaires

Merci Fge. ExecutorCompleterservice comptera sur Future.cancel et il ne s'interrogera que si le fil attend quelque chose. Maintenant, dans mon cas d'utilisation, j'ai une boucle infinie et je veux arrêter d'exécuter dès que l'itération actuelle est terminée. Dans mon cas d'utilisation, ce n'est pas bon si les itérations ont lieu même après l'annulation.


Que voulez-vous dire par "compter sur l'interruption"?


@shadowfax Voir le commentaire ci-dessus (je ne sais pas si vous l'avez vu), je ne comprends pas votre question.



1
votes

Je préférerais utiliser un sémaphore commun pour contrôler l'exécution et avoir une vérification fréquente dans les threads.

public class MyTask implements Runnable {
    private static volatile boolean isDone = false
    @Override
    public void run() {
        while(true) {
            if (isDone) {
                break;
            }

            // do some calculation, no wait() s

            if (...has result...) {
                isDone = true;
                break;
            }
        }
    }
}

Thread t1 = new Thread(new MyTask());
Thread t2 = new Thread(new MyTask());
Thread t3 = new Thread(new MyTask());
t1.start();
t2.start();
t3.start();


0 commentaires

0
votes

LOOK, vous pouvez conserver sur un tableau global partagé tous les objets de thread, puis à la fin de chaque tâche, vous pouvez effectuer un appel à une fonction "Nettoyage" qui prend simplement tous ces objets et effectue un appel à "interruption". sur eux. Cela ferait finir le premier fil de finition pour terminer l'exécution du reste.

import MyMain;
public class MyTaskI implements Runnable
{
   public void run()
   {
      //Do all the work
      for(Thread t : MyMain.workers)
      {
         // If it is not this thread
         t.interrupt();
      }
   }
}


2 commentaires

Comme l'OP mentionné, thread.Interrupt () s'appuie sur attendre état. Si le fil est ne pas attendre sur quoi que ce soit, cette solution ne fonctionnera pas.


Ensuite, vous pouvez faire une attente programmée minimale au début de chaque itération. S'il n'y a pas beaucoup de travail à faire sur chaque boucle, le délai ne devrait pas être un problème.