Wie kann man einfach warten, bis der gesamte Thread-Prozess abgeschlossen ist? Nehmen wir zum Beispiel an, ich habe:
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
}
}
Wie ändere ich dies, damit die main()
Methode beim Kommentar pausiert, bis alle run()
Methoden der Threads beendet werden? Vielen Dank!
java
multithreading
parallel-processing
wait
DivideByHero
quelle
quelle
Eine Möglichkeit wäre, eine machen
List
vonThread
s, erstellen und jeden Thread zu starten, während es in die Liste. Wenn alles gestartet ist, durchlaufen Sie die Liste erneut und rufen Siejoin()
jede einzelne auf. Es spielt keine Rolle, in welcher Reihenfolge die Threads ausgeführt werden. Sie müssen lediglich wissen, dass bis zum Ende der Ausführung der zweiten Schleife jeder Thread abgeschlossen ist.Ein besserer Ansatz ist die Verwendung eines ExecutorService und der zugehörigen Methoden:
Die Verwendung eines ExecutorService (und aller neuen Funktionen der Parallelitätsdienstprogramme von Java 5 ) ist unglaublich flexibel, und das obige Beispiel kratzt kaum an der Oberfläche.
quelle
quelle
Anstelle
join()
einer alten API können Sie auch CountDownLatch verwenden . Ich habe Ihren Code wie folgt geändert, um Ihre Anforderung zu erfüllen.Erklärung :
CountDownLatch
wurde mit der angegebenen Anzahl 1000 gemäß Ihrer Anforderung initialisiert.Jeder Worker-Thread
DoSomethingInAThread
dekrementiert denCountDownLatch
im Konstruktor übergebenen Thread .Hauptfaden
CountDownLatchDemo
await()
bis die Zählung Null geworden ist. Sobald der Zähler Null geworden ist, werden Sie in der Ausgabe unter die Linie gebracht.Weitere Informationen finden Sie auf der Oracle-Dokumentationsseite
Weitere Optionen finden Sie in der entsprechenden SE-Frage:
Warten Sie, bis alle Threads ihre Arbeit in Java beendet haben
quelle
Vermeiden Sie die Thread-Klasse insgesamt und verwenden Sie stattdessen die höheren Abstraktionen in java.util.concurrent
Die ExecutorService-Klasse stellt die Methode invokeAll bereit , die genau das zu tun scheint, was Sie wollen.
quelle
Erwägen Sie die Verwendung
java.util.concurrent.CountDownLatch
. Beispiele in Javadocsquelle
Wie Martin K vorgeschlagen hat,
java.util.concurrent.CountDownLatch
scheint dies eine bessere Lösung zu sein. Fügen Sie einfach ein Beispiel dafür hinzuquelle
Abhängig von Ihren Anforderungen möchten Sie möglicherweise auch die Klassen CountDownLatch und CyclicBarrier im Paket java.util.concurrent überprüfen. Sie können nützlich sein, wenn Sie möchten, dass Ihre Threads aufeinander warten, oder wenn Sie eine genauere Kontrolle über die Ausführung Ihrer Threads wünschen (z. B. wenn Sie in ihrer internen Ausführung darauf warten, dass ein anderer Thread einen bestimmten Status festlegt). Sie können auch einen CountDownLatch verwenden, um zu signalisieren, dass alle Ihre Threads gleichzeitig gestartet werden, anstatt sie einzeln zu starten, während Sie Ihre Schleife durchlaufen. Die Standard-API-Dokumente enthalten ein Beispiel dafür und verwenden einen anderen CountDownLatch, um darauf zu warten, dass alle Threads ihre Ausführung abgeschlossen haben.
quelle
Wenn Sie eine Liste der Threads erstellen, können Sie diese und .join () für jeden Thread durchlaufen, und Ihre Schleife wird beendet, wenn alle Threads vorhanden sind. Ich habe es aber nicht versucht.
http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#join ()
quelle
Erstellen Sie das Thread-Objekt in der ersten for-Schleife.
Und dann, was alle hier sagen.
quelle
Sie können dies mit dem Objekt "ThreadGroup" und seinem Parameter activeCount tun :
quelle
Alternativ zu CountDownLatch können Sie auch CyclicBarrier verwenden, z
Um CyclicBarrier in diesem Fall zu verwenden, sollte barriere.await () die letzte Anweisung sein, dh wenn Ihr Thread mit seiner Arbeit fertig ist. CyclicBarrier kann mit seiner reset () -Methode wieder verwendet werden. Um Javadocs zu zitieren:
Ein CyclicBarrier unterstützt einen optionalen Runnable-Befehl, der einmal pro Barrierepunkt ausgeführt wird, nachdem der letzte Thread in der Gruppe eingetroffen ist, bevor jedoch Threads freigegeben werden. Diese Barriereaktion ist nützlich, um den Status des gemeinsam genutzten Status zu aktualisieren, bevor eine der Parteien fortfährt.
quelle
Das
join()
war mir nicht hilfreich. siehe dieses Beispiel in Kotlin:Das Ergebnis:
Lassen Sie mich jetzt die
join()
für Threads verwenden:Und das Ergebnis:
Wie es klar ist, wenn wir Folgendes verwenden
join
:Unsere Lösung, um das Blockieren anderer Threads zu verhindern, bestand darin, eine ArrayList zu erstellen:
Wenn wir nun einen neuen Thread starten möchten, fügen wir ihn meistens der ArrayList hinzu:
Die
addThreadToArray
Funktion:Die
startNewThread
Funktion:Überprüfen Sie die Vervollständigung der Threads wie unten beschrieben, wo immer dies erforderlich ist:
quelle