Die Thread.join () -Methode in Java

1. Übersicht

In diesem Tutorial werden die verschiedenen join () -Methoden in der Thread- Klasse erläutert . Wir werden auf die Details dieser Methoden und einige Beispielcodes eingehen.

Wie die wait () und benachrichtigt () -Methoden , join () ist ein weiterer Mechanismus der inter Thread - Synchronisation.

In diesem Tutorial können Sie einen kurzen Blick auf wait () und notify () werfen .

2. Die Thread.join () Methode

Die Join-Methode ist in der Thread- Klasse definiert:

public final void join () löst InterruptedException aus

Wartet darauf, dass dieser Thread stirbt.

Wenn wir die join () -Methode für einen Thread aufrufen, wird der aufrufende Thread in einen Wartezustand versetzt. Es bleibt in einem Wartezustand, bis der referenzierte Thread beendet wird.

Wir können dieses Verhalten im folgenden Code sehen:

class SampleThread extends Thread { public int processingCount = 0; SampleThread(int processingCount) { this.processingCount = processingCount; LOGGER.info("Thread Created"); } @Override public void run() { LOGGER.info("Thread " + this.getName() + " started"); while (processingCount > 0) { try { Thread.sleep(1000); } catch (InterruptedException e) { LOGGER.info("Thread " + this.getName() + " interrupted"); } processingCount--; } LOGGER.info("Thread " + this.getName() + " exiting"); } } @Test public void givenStartedThread_whenJoinCalled_waitsTillCompletion() throws InterruptedException { Thread t2 = new SampleThread(1); t2.start(); LOGGER.info("Invoking join"); t2.join(); LOGGER.info("Returned from join"); assertFalse(t2.isAlive()); } 

Bei der Ausführung des Codes sollten ähnliche Ergebnisse erwartet werden:

INFO: Thread Created INFO: Invoking join INFO: Thread Thread-1 started INFO: Thread Thread-1 exiting INFO: Returned from join

Die join () -Methode kann auch zurückgegeben werden, wenn der referenzierte Thread unterbrochen wurde . In diesem Fall löst die Methode eine InterruptedException aus .

Schließlich , wenn das referenzierte Thread bereits beendet wurde oder nicht gestartet wurde, um den Anruf join () Methode gibt sofort .

Thread t1 = new SampleThread(0); t1.join(); //returns immediately

3. Thread.join () -Methoden mit Timeout

Die join () -Methode wartet weiter, wenn der referenzierte Thread blockiert ist oder die Verarbeitung zu lange dauert. Dies kann zu einem Problem werden, da der aufrufende Thread nicht mehr reagiert. Um diese Situationen zu bewältigen, verwenden wir überladene Versionen der join () -Methode, mit denen wir eine Zeitüberschreitung angeben können.

Es gibt zwei zeitgesteuerte Versionen, die die join () -Methode überladen :

“Public Final Void Join (Long Millis ) löst InterruptedException aus

Wartet höchstens Millis Millisekunden, bis dieser Thread stirbt. Eine Zeitüberschreitung von 0 bedeutet, für immer zu warten. “

“Public Final Void Join (Long Millis, Intnanos ) löst InterruptedException aus

Wartet höchstens Millis Millisekunden plus Nanos Nanosekunden, bis dieser Thread stirbt. “

Wir können den zeitgesteuerten join () wie folgt verwenden:

@Test public void givenStartedThread_whenTimedJoinCalled_waitsUntilTimedout() throws InterruptedException { Thread t3 = new SampleThread(10); t3.start(); t3.join(1000); assertTrue(t3.isAlive()); } 

In diesem Fall wartet der aufrufende Thread ungefähr 1 Sekunde, bis der Thread t3 beendet ist. Wenn der Thread t3 in diesem Zeitraum nicht beendet wird, gibt die join () -Methode die Steuerung an die aufrufende Methode zurück.

Timed join () ist für das Timing vom Betriebssystem abhängig. Wir können also nicht davon ausgehen, dass join () genau so lange wartet, wie angegeben.

4. Thread.join () Methoden und Synchronisation

Das Aufrufen der join () -Methode wartet nicht nur bis zur Beendigung, sondern hat auch einen Synchronisationseffekt. join () erstellt eine Vorher-Beziehung:

"Alle Aktionen in einem Thread werden ausgeführt, bevor ein anderer Thread erfolgreich von einem join () in diesem Thread zurückgegeben wird."

Dies bedeutet, dass, wenn ein Thread t1 t2.join () aufruft, alle von t2 vorgenommenen Änderungen bei der Rückkehr in t1 sichtbar sind. Wenn wir jedoch join () nicht aufrufen oder andere Synchronisationsmechanismen verwenden, können wir nicht garantieren, dass Änderungen im anderen Thread für den aktuellen Thread sichtbar sind, selbst wenn der andere Thread abgeschlossen ist.

Obwohl der Aufruf der Methode join () für einen Thread im terminierten Zustand sofort zurückgegeben wird, müssen wir ihn in einigen Situationen dennoch aufrufen.

Im Folgenden sehen Sie ein Beispiel für falsch synchronisierten Code:

SampleThread t4 = new SampleThread(10); t4.start(); // not guaranteed to stop even if t4 finishes. do { } while (t4.processingCount > 0);

Um den obigen Code richtig zu synchronisieren, können wir zeitgesteuertes t4.join () in die Schleife einfügen oder einen anderen Synchronisationsmechanismus verwenden.

5. Schlussfolgerung

Die Methode join () ist sehr nützlich für die Synchronisation zwischen Threads. In diesem Artikel haben wir die join () -Methoden und ihr Verhalten erläutert . Wir haben auch den Code mit der join () -Methode überprüft .

Wie immer finden Sie den vollständigen Quellcode auf GitHub.