Ich schreibe eine Anwendung mit 5 Threads, die gleichzeitig Informationen aus dem Web abrufen und 5 verschiedene Felder in einer Pufferklasse ausfüllen.
Ich muss Pufferdaten validieren und in einer Datenbank speichern, wenn alle Threads ihren Job beendet haben.
Wie kann ich das tun (benachrichtigt werden, wenn alle Threads ihre Arbeit beendet haben)?
java
multithreading
wait
RYN
quelle
quelle
Antworten:
Der Ansatz, den ich verfolge, besteht darin, einen ExecutorService zum Verwalten von Thread-Pools zu verwenden.
quelle
while(!es.awaitTermination(1, TimeUnit.MINUTES));
es.shutdown();
? Was ist, wenn ich einen Code schreibe, in dem ich einen Thread mites.execute(runnableObj_ZipMaking);
intry
block ausgeführt und infinally
aufgerufen habeboolean finshed = es.awaitTermination(10, TimeUnit.MINUTES);
? Ich nehme an, dies sollte warten, bis alle Threads ihre Arbeit abgeschlossen haben oder eine Zeitüberschreitung eingetreten ist (was auch immer zuerst ist). Ist meine Annahme richtig? oder anrufenshutdown()
ist obligatorisch?Sie können
join
zu den Threads. Der Join wird blockiert, bis der Thread abgeschlossen ist.Beachten Sie, dass
join
einInterruptedException
. In diesem Fall müssen Sie entscheiden, was zu tun ist (z. B. versuchen Sie, die anderen Threads abzubrechen, um unnötige Arbeiten zu vermeiden).quelle
t.join();
bedeutet, dass der aktuelle Thread blockiert, bis der Threadt
beendet wird. Der Thread ist davon nicht betroffent
.Schauen Sie sich verschiedene Lösungen an.
join()
Die API wurde in früheren Versionen von Java eingeführt. Seit der Veröffentlichung von JDK 1.5 sind mit diesem gleichzeitigen Paket einige gute Alternativen verfügbar .ExecutorService # invokeAll ()
In dieser verwandten SE-Frage finden Sie ein Codebeispiel:
Wie verwende ich invokeAll (), um alle Thread-Pools ihre Aufgabe erledigen zu lassen?
CountDownLatch
Beziehen Sie sich auf diese Frage für die Verwendung von
CountDownLatch
Wie kann man auf einen Thread warten, der einen eigenen Thread erzeugt?
ForkJoinPool oder newWorkStealingPool () in Executors
Durchlaufen Sie alle zukünftigen Objekte, die nach dem Senden an erstellt wurden
ExecutorService
quelle
Neben den
Thread.join()
Vorschlägen anderer führte Java 5 das Executor-Framework ein. Dort arbeitet man nicht mitThread
Objekten. Stattdessen senden Sie IhreCallable
oderRunnable
Objekte an einen Executor. Es gibt einen speziellen Executor, der mehrere Aufgaben ausführen und deren Ergebnisse nicht in der richtigen Reihenfolge zurückgeben soll. Das ist dasExecutorCompletionService
:Dann können Sie wiederholt aufrufen,
take()
bis keineFuture<?>
Objekte mehr zurückgegeben werden müssen, was bedeutet, dass alle abgeschlossen sind.Eine andere Sache, die abhängig von Ihrem Szenario relevant sein kann, ist
CyclicBarrier
.quelle
executor.submit
gibt a zurückFuture<?>
. Ich würde diese Futures zu einer Liste hinzufügen und dann die Liste durchlaufen, dieget
jede Zukunft aufruft .Executors
z. B.Executors.newCachedThreadPool
(oder ähnliches)Eine andere Möglichkeit ist das
CountDownLatch
Objekt, das für einfache Situationen nützlich ist: Da Sie die Anzahl der Threads im Voraus kennen, initialisieren Sie es mit der entsprechenden Anzahl und übergeben die Referenz des Objekts an jeden Thread.Nach Abschluss seiner Aufgabe ruft jeder Thread auf,
CountDownLatch.countDown()
wodurch der interne Zähler dekrementiert wird. Der Hauptthread sollte nach dem Starten aller anderen denCountDownLatch.await()
Blockierungsaufruf ausführen. Es wird freigegeben, sobald der interne Zähler 0 erreicht hat.Achten Sie darauf, dass mit diesem Objekt auch ein
InterruptedException
geworfen werden kann.quelle
Sie machen
Nach dieser for-Schleife können Sie sicher sein, dass alle Threads ihre Jobs beendet haben.
quelle
Warten / blockieren Sie den Thread Main, bis einige andere Threads ihre Arbeit abgeschlossen haben.
Wie
@Ravindra babu
gesagt, es kann auf verschiedene Arten erreicht werden, aber anhand von Beispielen gezeigt werden.java.lang.Thread. join () Seit: 1.0
java.util.concurrent.CountDownLatch Seit: 1.5
.countDown()
«Verringert die Anzahl der Latch-Gruppen..await()
«Die Wartemethoden blockieren, bis die aktuelle Anzahl Null erreicht.Wenn Sie erstellt
latchGroupCount = 4
danncountDown()
sollten 4 mal aufgerufen werden , um 0. So zu stellen rechnen, dassawait()
wird die Sperrfäden lösen.Beispielcode der Threaded-Klasse
LatchTask
. Um den Ansatz zu testen, verwenden SiejoiningThreads();
undlatchThreads();
von der Hauptmethode.Executer-Framework: Mit ExecutorService können wir einen Thread-Pool erstellen und den Fortschritt der asynchronen Aufgaben mit Future verfolgen.
submit(Runnable)
,submit(Callable)
die Future Object zurückgeben. Mit derfuture.get()
Funktion können wir den Haupt-Thread blockieren, bis der Arbeitsthread seine Arbeit beendet hat.invokeAll(...)
- gibt eine Liste zukünftiger Objekte zurück, über die Sie die Ergebnisse der Ausführungen der einzelnen Callable abrufen können.Hier finden Sie ein Beispiel für die Verwendung von Interfaces Runnable, Callable with Executor Framework.
@Siehe auch
quelle
Speichern Sie die Thread-Objekte in einer Sammlung (wie einer Liste oder einem Set), durchlaufen Sie dann die Sammlung, sobald die Threads gestartet sind, und rufen Sie join () für die Threads auf.
quelle
Zu diesem Zweck können Sie die Threadf # -Verbindungsmethode verwenden.
quelle
Obwohl dies für das Problem von OP nicht relevant ist, können Sie einen Exchanger verwenden , wenn Sie an einer Synchronisation (genauer gesagt einem Rendez-Vous) mit genau einem Thread interessiert sind
In meinem Fall musste ich den übergeordneten Thread anhalten, bis der untergeordnete Thread etwas getan hat, z. B. seine Initialisierung abgeschlossen hat. Ein CountDownLatch funktioniert auch gut.
quelle
Ein Executor-Service kann verwendet werden, um mehrere Threads einschließlich Status und Abschluss zu verwalten. Siehe http://programmingexamples.wikidot.com/executorservice
quelle
versuchen Sie dies, wird funktionieren.
quelle
Ich hatte ein ähnliches Problem und verwendete schließlich Java 8 parallelStream.
Es ist super einfach und lesbar. Hinter den Kulissen wird der Standard-Fork-Join-Pool von JVM verwendet. Dies bedeutet, dass gewartet wird, bis alle Threads abgeschlossen sind, bevor Sie fortfahren. Für meinen Fall war es eine ordentliche Lösung, da es der einzige parallelStream in meiner Anwendung war. Wenn mehr als ein parallelStream gleichzeitig ausgeführt wird, lesen Sie bitte den folgenden Link.
Weitere Informationen zu parallelen Streams finden Sie hier .
quelle
Die vorhandenen Antworten besagten, könnte
join()
jeder Thread.Es gibt jedoch mehrere Möglichkeiten, um das Thread-Array / die Thread-Liste abzurufen:
ThreadGroup
diese Option , um die Threads zu verwalten.Der folgende Code verwendet den
ThreadGruop
Ansatz. Es wird zuerst eine Gruppe erstellt. Wenn Sie dann jeden Thread erstellen, geben Sie die Gruppe im Konstruktor an. Später kann das Thread-Array über abgerufen werdenThreadGroup.enumerate()
Code
SyncBlockLearn.java
Der Haupt-Thread wartet, bis alle Threads in der Gruppe beendet sind.
quelle
Ich habe eine kleine Hilfsmethode erstellt, um auf das Ende einiger Threads zu warten:
quelle
Verwenden Sie dies in Ihrem Hauptthread: while (! Executor.isTerminated ()); Fügen Sie diese Codezeile ein, nachdem Sie alle Threads vom Executor-Dienst gestartet haben. Dadurch wird der Hauptthread erst gestartet, nachdem alle von Executoren gestarteten Threads abgeschlossen sind. Stellen Sie sicher, dass Sie executor.shutdown () aufrufen. vor der obigen Schleife.
quelle