Was bedeutet dieser Thread Join-Code?

Was bedeuten in diesem Code die beiden Punkte? t1.join() bewirkt, dass t2 stoppt, bis t1 beendet wird?

 Thread t1 = new Thread(new EventThread("e1")); t1.start(); Thread t2 = new Thread(new EventThread("e2")); t2.start(); while (true) { try { t1.join(); t2.join(); break; } catch (InterruptedException e) { e.printStackTrace(); } } 

Um von der Thread.join() -Methode zu zitieren , javadocs :

join() Wartet darauf, dass dieser Thread stirbt.

Es gibt einen Thread, der den Beispielcode ausführt, der wahrscheinlich der Hauptthread ist .

  1. Der Hauptthread erstellt und startet die Threads t1 und t2 . Die beiden Threads beginnen parallel zu laufen.
  2. Der Haupt-Thread ruft t1.join() auf, um auf den Abschluss des t1 Threads zu warten.
  3. Der Thread t1 wird abgeschlossen und die Methode t1.join() wird im Hauptthread zurückgegeben. Beachten Sie, dass t1 bereits abgeschlossen sein könnte, bevor der Aufruf von join() wird. In diesem Fall wird der Aufruf von join() sofort zurückgegeben.
  4. Der Hauptthread ruft t2.join() auf, um auf den Abschluss des t2 Threads zu warten.
  5. Der t2 Thread wird abgeschlossen (oder er wurde möglicherweise abgeschlossen, bevor der t1 Thread ausgeführt wurde) und die t2.join() -Methode wird im Hauptthread zurückgegeben.

Es ist wichtig zu verstehen, dass die t1 und t2 Threads parallel ausgeführt wurden, aber der Hauptthread, der sie gestartet hat, muss warten, bis sie beendet sind, bevor er fortfahren kann. Das ist ein übliches Muster. Außerdem könnten t1 und / oder t2 beendet sein, bevor der Hauptthread sie join() aufruft. Wenn ja, wird join() nicht warten, sondern sofort zurückkehren.

t1.join() bedeutet, dass t2 stoppt, bis t1 beendet wird?

Nein. Der Hauptthread, der t1.join() wird nicht mehr ausgeführt und wartet, bis der t1 Thread beendet ist. Der t2 Thread läuft parallel und wird von t1 oder dem Aufruf t1.join() überhaupt nicht beeinflusst.

In Bezug auf try / catch gibt join() InterruptedException was bedeutet, dass der Haupt-Thread, der join() aufruft join() selbst von einem anderen Thread unterbrochen werden kann.

 while (true) { 

Die Joins in einer while Schleife sind ein seltsames Muster. Normalerweise würden Sie den ersten Join und dann den zweiten Join ausführen, der die InterruptedException in jedem Fall entsprechend behandelt. Keine Notwendigkeit, sie in eine Schleife zu setzen.

Dies ist eine beliebte Java-Interviewfrage .

 Thread t1 = new Thread(new EventThread("e1")); t1.start(); Thread e2 = new Thread(new EventThread("e2")); t2.start(); while (true) { try { t1.join(); // 1 t2.join(); // 2 These lines (1,2) are in in public static void main break; } } 

t1.join() bedeutet, t1 sagt etwas wie ” Ich möchte zuerst beenden “. Das Gleiche gilt für t2 . Egal wer t1 oder t2 thread gestartet hat (in diesem Fall die Hauptmethode), main wartet, bis t1 und t2 ihre Aufgabe beenden.

Ein wichtiger Punkt, der notiert werden muss, ist jedoch, dass t1 und t2 selbst unabhängig von der Join- t1 auf t1 und t2 parallel ablaufen können . Es ist der main/daemon Thread, der warten muss .

join() bedeutet, dass ein Thread beendet werden muss. Dies ist eine Blockiermethode. Ihr Hauptthread (derjenige, der join() t1.join() ) wird auf der t1.join() Zeile warten, bis t1 seine Arbeit beendet hat, und wird dann dasselbe für t2.join() tun.

Ein Bild sagt mehr als tausend Worte.

  Main thread-->----->--->-->--block##########continue--->----> \ | | sub thread start()\ | join() | \ | | ---sub thread----->--->--->--finish 

Hoffen Sie, nützlich zu sein, für mehr Details klicken Sie hier

Wenn der Thread tA tB.join () aufruft, wartet seine Ursache nicht nur darauf, dass tB stirbt, oder tA wird selbst unterbrochen, sondern erzeugt vor der Beziehung zwischen der letzten statement in tB und der nächsten statement nach tB.join () in tA thread.

Alle Aktionen in einem Thread werden ausgeführt, bevor ein anderer Thread erfolgreich von einem Join () für diesen Thread zurückgegeben wird.

Es bedeutet Programm

 class App { // shared, not synchronized variable = bad practice static int sharedVar = 0; public static void main(String[] args) throws Exception { Thread threadB = new Thread(() -> {sharedVar = 1;}); threadB.start(); threadB.join(); while (true) System.out.print(sharedVar); } } 

Immer drucken

 >> 1111111111111111111111111 ... 

Aber Programm

 class App { // shared, not synchronized variable = bad practice static int sharedVar = 0; public static void main(String[] args) throws Exception { Thread threadB = new Thread(() -> {sharedVar = 1;}); threadB.start(); // threadB.join(); COMMENT JOIN while (true) System.out.print(sharedVar); } } 

Kann nicht nur drucken

 >> 0000000000 ... 000000111111111111111111111111 ... 

Aber

 >> 00000000000000000000000000000000000000000000 ... 

Immer nur ‘0’.

Da das Java Memory Model keinen neuen Wert von ‘sharedVar’ von threadB in den Hauptthread übergibt, ohne hepps-before-relation (Thread-Start, Thread-Join, Verwendung des ‘synchronisierten’ Schlüsselworts, Verwendung von AtomicXXX-Variablen usw.).

Von oracle Dokumentationsseite auf Joins

Die join Methode ermöglicht es einem Thread, auf die Fertigstellung eines anderen Threads zu warten.

Wenn t1 ein Thread Objekt ist, dessen Thread gerade ausgeführt wird,

 t1.join() : causes the current thread to pause execution until t1's thread terminates. 

Wenn t2 ein Thread Objekt ist, dessen Thread gerade ausgeführt wird,

 t2.join(); causes the current thread to pause execution until t2's thread terminates. 

join API ist eine Low-Level-API, die in früheren Versionen von Java eingeführt wurde. Viele Dinge wurden im Laufe der Zeit (vor allem mit jdk 1.5 Release) auf Nebenläufigkeit Front geändert.

Sie können dasselbe mit der java.util.concurrent-API erreichen. Einige der Beispiele sind

  1. Verwenden von InvokeAll für ExecutorService
  2. Verwenden von CountDownLatch
  3. Verwenden von ForkJoinPool oder newWorkStealingPool von Executors (seit Java 8)

Beziehen Sie sich auf verwandte SE Fragen:

warte, bis alle Threads ihre Arbeit in Java beendet haben

Einfach gesagt:
t1.join() kehrt zurück, nachdem t1 abgeschlossen ist.
Es tut nichts, um t1 zu t1 , außer zu warten, bis es fertig ist.
Natürlich wird der Code nach t1.join() erst ausgeführt, nachdem t1.join() zurückgegeben wurde.

Nehmen wir an, unser Hauptthread startet die Threads t1. Irgendwann wird unser Haupt-Thread die Ausführung beenden.
Wenn wir nun die Methode t1.join () nicht aufrufen, wird der Haupt-Thread beendet und in diesem Fall erhält t1 keine Chance, die Ausführung zu beenden.
Die Join () -Methode stellt also sicher, dass der aufrufende Thread, der in diesem Fall der Hauptthread ist, nach der Ausführung darauf wartet, dass t1 die Ausführung beendet.
Sobald t1 fertig ausgeführt ist, kann der Haupt-Thread beendet werden.