118 votes

Comment attendre la fin d'un certain nombre de threads ?

Quel est le moyen d'attendre simplement la fin de tous les processus threadés ? Par exemple, disons que j'ai :

public class DoSomethingInAThread implements Runnable{

    public static void main(String[] args) {
        for (int n=0; n<1000; n++) {
            Thread t = new Thread(new DoSomethingInAThread());
            t.start();
        }
        // wait for all threads' run() methods to complete before continuing
    }

    public void run() {
        // do something here
    }

}

Comment puis-je modifier cela pour que le main() La méthode s'arrête au commentaire jusqu'à ce que tous les fils de discussion run() sortie des méthodes ? Merci !

166voto

Martin v. Löwis Points 61768

Vous mettez tous les fils dans un tableau, vous les démarrez tous, puis vous avez une boucle

for(i = 0; i < threads.length; i++)
  threads[i].join();

Chaque jointure se bloquera jusqu'à ce que le fil d'exécution respectif soit terminé. Les threads peuvent se terminer dans un ordre différent de celui dans lequel vous les avez joints, mais ce n'est pas un problème : lorsque la boucle sort, tous les threads sont terminés.

1 votes

@Mykola : quoi exactement Quel est l'avantage d'utiliser un groupe de fils ? Ce n'est pas parce que l'API existe que vous devez l'utiliser...

0 votes

Merci. Je vais regarder dans ThreadGroup, mais utiliser join() semble tellement plus simple pour travailler avec du code existant !

2 votes

Voyez : "Un groupe de threads représente un ensemble de threads". C'est sémantiquement correct pour ce cas d'utilisation ! Et : "Un thread est autorisé à accéder aux informations concernant son propre groupe de threads".

42voto

Adam Batkin Points 20920

Un moyen serait de faire un List de Thread s, créer et lancer chaque thread, tout en l'ajoutant à la liste. Une fois que tout est lancé, bouclez à nouveau dans la liste et appelez join() sur chacun d'eux. L'ordre d'exécution des threads n'a pas d'importance, tout ce que vous devez savoir, c'est qu'au moment où la deuxième boucle termine son exécution, tous les threads auront terminé.

Une meilleure approche consiste à utiliser un ExecutorService et ses méthodes associées :

List<Callable> callables = ... // assemble list of Callables here
                               // Like Runnable but can return a value
ExecutorService execSvc = Executors.newCachedThreadPool();
List<Future<?>> results = execSvc.invokeAll(callables);
// Note: You may not care about the return values, in which case don't
//       bother saving them

L'utilisation d'un ExecutorService (et toutes les nouveautés de Java 5) utilitaires de concurrence ) est incroyablement flexible, et l'exemple ci-dessus ne fait qu'effleurer la surface.

0 votes

ThreadGroup est la solution ! Avec une liste mutable, vous allez avoir des problèmes (synchronisation).

3 votes

Quoi ? Comment pourrais-tu avoir des problèmes ? Elle n'est mutable (ne peut être lue) que par le thread qui effectue le lancement, donc tant qu'il ne modifie pas la liste tandis que en l'itérant, c'est bon.

0 votes

Cela dépend de la façon dont vous l'utilisez. Si vous utilisez la classe appelante dans un thread, vous aurez des problèmes.

27voto

jt. Points 3116
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class DoSomethingInAThread implements Runnable
{
   public static void main(String[] args) throws ExecutionException, InterruptedException
   {
      //limit the number of actual threads
      int poolSize = 10;
      ExecutorService service = Executors.newFixedThreadPool(poolSize);
      List<Future<Runnable>> futures = new ArrayList<Future<Runnable>>();

      for (int n = 0; n < 1000; n++)
      {
         Future f = service.submit(new DoSomethingInAThread());
         futures.add(f);
      }

      // wait for all tasks to complete before continuing
      for (Future<Runnable> f : futures)
      {
         f.get();
      }

      //shut down the executor service so that this thread can exit
      service.shutdownNow();
   }

   public void run()
   {
      // do something here
   }
}

0 votes

Cela a fonctionné comme un charme... J'ai deux ensembles de threads qui ne devraient pas fonctionner simultanément en raison de problèmes sur plusieurs cookies. J'ai utilisé votre exemple pour exécuter un jeu de threads à la fois... merci de partager vos connaissances...

0 votes

@Dantalian - Dans votre classe Runnable (probablement dans la méthode run), vous voudriez capturer toutes les exceptions qui se produisent et les stocker localement (ou stocker un message/condition d'erreur). Dans l'exemple, f.get() renvoie l'objet que vous avez soumis à l'ExecutorService. Votre objet pourrait être doté d'une méthode permettant de récupérer les éventuelles exceptions/conditions d'erreur. En fonction de la façon dont vous modifiez l'exemple fourni, vous devrez peut-être convertir l'objet retourné par f.get() en votre type attendu.

8voto

henrik Points 410

Évitez complètement la classe Thread et utilisez plutôt les abstractions supérieures fournies par java.util.concurrent.

La classe ExecutorService fournit le méthode invokeAll qui semble faire exactement ce que vous voulez.

3voto

David Points 1862

Si vous faites une liste des fils, vous pouvez les parcourir en boucle et .join() contre chacun d'eux, et votre boucle se terminera lorsque tous les fils l'auront fait. Je ne l'ai pas encore essayé.

[http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#join()](http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#join())

0 votes

Bonjour, cela n'a pas fonctionné pour moi pour une raison quelconque. Voici ma question : stackoverflow.com/users/5144855/ruchir-baronia

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