J'écris une application qui a 5 threads qui obtiennent des informations du Web simultanément et remplissent 5 champs différents dans une classe de tampon.
J'ai besoin de valider les données du tampon et de les stocker dans une base de données lorsque tous les threads ont terminé leur travail.
Comment puis-je faire cela (être alerté lorsque tous les threads ont terminé leur travail)?
91
Réponses:
L'approche que j'adopte consiste à utiliser un ExecutorService pour gérer des pools de threads.
la source
while(!es.awaitTermination(1, TimeUnit.MINUTES));
es.shutdown();
? que se passe-t-il si j'écris un code dans lequel j'exécute un thread en utilisantes.execute(runnableObj_ZipMaking);
intry
block et infinally
I calledboolean finshed = es.awaitTermination(10, TimeUnit.MINUTES);
. Donc, je suppose que cela devrait attendre que tous les threads aient terminé leur travail ou que le délai d'attente se produise (quel que soit le premier), mon hypothèse est-elle correcte? ou appelershutdown()
est obligatoire?Vous pouvez
join
les fils. La jointure se bloque jusqu'à ce que le thread se termine.Notez que
join
jette unInterruptedException
. Vous devrez décider quoi faire si cela se produit (par exemple, essayez d'annuler les autres threads pour éviter un travail inutile).la source
t.join();
signifie que le thread actuel se bloque jusqu'à ce que le thread set
termine. Cela n'affecte pas le filt
.Jetez un œil à diverses solutions.
join()
L'API a été introduite dans les premières versions de Java. Certaines bonnes alternatives sont disponibles avec ce package simultané depuis la version JDK 1.5.ExecutorService # invokeAll ()
Reportez-vous à cette question SE associée pour un exemple de code:
Comment utiliser invokeAll () pour laisser tous les pools de threads faire leur tâche?
CountDownLatch
Reportez-vous à cette question pour l'utilisation de
CountDownLatch
Comment attendre un thread qui génère son propre thread?
ForkJoinPool ou newWorkStealingPool () dans les exécuteurs
Parcourez tous les objets Future créés après avoir été soumis à
ExecutorService
la source
Mis à part
Thread.join()
suggéré par d'autres, java 5 a introduit le framework exécuteur. Là, vous ne travaillez pas avec desThread
objets. Au lieu de cela, vous soumettez vos objetsCallable
ouRunnable
à un exécuteur testamentaire. Il existe un exécuteur spécial destiné à exécuter plusieurs tâches et à renvoyer leurs résultats dans le désordre. C'est çaExecutorCompletionService
:Ensuite, vous pouvez appeler à plusieurs reprises
take()
jusqu'à ce qu'il n'y ait plus d'Future<?>
objets à renvoyer, ce qui signifie qu'ils sont tous terminés.Une autre chose qui peut être pertinente, selon votre scénario est
CyclicBarrier
.la source
executor.submit
renvoie unFuture<?>
. J'ajouterais ces futurs à une liste, puis je bouclerais la liste appelantget
chaque avenir.Executors
, par exemple,Executors.newCachedThreadPool
(ou similaire)Une autre possibilité est l'
CountDownLatch
objet, qui est utile pour des situations simples: puisque vous connaissez à l'avance le nombre de threads, vous l'initialisez avec le décompte pertinent, et passez la référence de l'objet à chaque thread.À la fin de sa tâche, chaque thread appelle
CountDownLatch.countDown()
ce qui décrémente le compteur interne. Le thread principal, après avoir démarré tous les autres, doit faire l'CountDownLatch.await()
appel de blocage. Il sera libéré dès que le compteur interne aura atteint 0.Faites attention qu'avec cet objet, un
InterruptedException
peut également être lancé.la source
Tu fais
Après cette boucle for, vous pouvez être sûr que tous les threads ont terminé leur travail.
la source
Attendez / bloquez le fil principal jusqu'à ce que d'autres threads aient terminé leur travail.
Comme
@Ravindra babu
dit, cela peut être réalisé de différentes manières, mais en montrant des exemples.java.lang.Thread. join () Depuis: 1.0
java.util.concurrent.CountDownLatch depuis: 1.5
.countDown()
«Décrémente le nombre du groupe de verrouillage..await()
«Les méthodes d'attente se bloquent jusqu'à ce que le décompte actuel atteigne zéro.Si vous avez créé,
latchGroupCount = 4
alorscountDown()
devrait être appelé 4 fois pour faire le compte 0. Donc, celaawait()
libérera les threads de blocage.Exemple de code de classe Threaded
LatchTask
. Pour tester l'utilisation de l'approchejoiningThreads();
etlatchThreads();
de la méthode principale.Framework Executer: nous pouvons utiliser ExecutorService pour créer un pool de threads et suivre la progression des tâches asynchrones avec Future.
submit(Runnable)
,submit(Callable)
qui renvoient Future Object. En utilisant lafuture.get()
fonction, nous pouvons bloquer le thread principal jusqu'à ce que les threads de travail terminent leur travail.invokeAll(...)
- retourne une liste d'objets Future via laquelle vous pouvez obtenir les résultats des exécutions de chaque Callable.Trouvez un exemple d'utilisation d'Interfaces Runnable, Callable with Executor Framework.
@Voir également
la source
Stockez les objets Thread dans une collection (comme une liste ou un ensemble), puis parcourez la collection une fois que les threads sont démarrés et appelez join () sur les threads.
la source
Vous pouvez utiliser la méthode Threadf # join à cet effet.
la source
Bien que cela ne concerne pas le problème d'OP, si vous êtes intéressé par la synchronisation (plus précisément, un rendez-vous) avec exactement un thread, vous pouvez utiliser un échangeur
Dans mon cas, j'avais besoin de mettre en pause le thread parent jusqu'à ce que le thread enfant fasse quelque chose, par exemple acheva son initialisation. Un CountDownLatch fonctionne également bien.
la source
Un service exécuteur peut être utilisé pour gérer plusieurs threads, y compris l'état et l'achèvement. Voir http://programmingexamples.wikidot.com/executorservice
la source
essayez ceci, fonctionnera.
la source
J'ai eu un problème similaire et j'ai fini par utiliser Java 8 parallelStream.
C'est super simple et lisible. Dans les coulisses, il utilise le pool de jointure fork de la JVM par défaut, ce qui signifie qu'il attendra que tous les threads se terminent avant de continuer. Pour mon cas, c'était une solution intéressante, car c'était le seul parallelStream de mon application. Si vous avez plus d'un parallelStream en cours d'exécution simultanément, veuillez lire le lien ci-dessous.
Plus d'informations sur les flux parallèles ici .
la source
Les réponses existantes ont dit pourrait
join()
chaque fil.Mais il existe plusieurs façons d'obtenir le tableau / la liste des threads:
ThreadGroup
pour gérer les threads.Le code suivant utilisera l'
ThreadGruop
approche. Il crée d'abord un groupe, puis lors de la création de chaque thread, spécifiez le groupe dans le constructeur, plus tard pourrait obtenir le tableau de thread viaThreadGroup.enumerate()
Code
SyncBlockLearn.java
Le thread principal attendra que tous les threads du groupe se terminent.
la source
J'ai créé une petite méthode d'aide pour attendre la fin de quelques threads:
la source
Utilisez ceci dans votre thread principal: while (! Executor.isTerminated ()); Mettez cette ligne de code après avoir démarré tous les threads du service exécuteur. Cela ne démarrera le thread principal qu'une fois tous les threads démarrés par les exécuteurs terminés. Assurez-vous d'appeler executor.shutdown (); avant la boucle ci-dessus.
la source