De methode Thread.join () in Java

1. Overzicht

In deze tutorial bespreken we de verschillende toetreden () methoden in de Draad klasse. We zullen ingaan op de details van deze methoden en wat voorbeeldcode.

Zoals de wacht() en meld () methoden, toetreden () is een ander mechanisme van synchronisatie tussen threads.

U kunt deze tutorial snel bekijken om er meer over te lezen wacht() en melden ().

2. Het Thread.join () Methode

De join-methode is gedefinieerd in het Draad klasse:

public final void join () gooit InterruptedException

Wacht tot deze draad dood is.

Wanneer we het toetreden () methode op een thread, gaat de aanroepende thread in een wachtstatus. Het blijft in een wachttoestand totdat de thread waarnaar wordt verwezen, wordt beëindigd.

We kunnen dit gedrag zien in de volgende code:

klasse SampleThread breidt Thread {public int processingCount = 0; SampleThread (int processingCount) {this.processingCount = processingCount; LOGGER.info ("Discussie gemaakt"); } @Override public void run () {LOGGER.info ("Thread" + this.getName () + "gestart"); while (processingCount> 0) {probeer {Thread.sleep (1000); } catch (InterruptedException e) {LOGGER.info ("Thread" + this.getName () + "onderbroken"); } processingCount--; } LOGGER.info ("Discussie" + this.getName () + "afsluiten"); }} @Test openbare leegte gegevenStartedThread_whenJoinCalled_waitsTillCompletion () gooit InterruptedException {Thread t2 = nieuwe SampleThread (1); t2.start (); LOGGER.info ("Join aanroepen"); t2.join (); LOGGER.info ("Teruggekeerd van deelname"); assertFalse (t2.isAlive ()); } 

We zouden resultaten moeten verwachten die vergelijkbaar zijn met de volgende bij het uitvoeren van de code:

INFO: Thread aangemaakt INFO: Join aanroepen INFO: Thread Thread-1 gestart INFO: Thread Thread-1 verlaten INFO: Teruggekeerd van join

De toetreden () methode kan ook terugkeren als de thread waarnaar wordt verwezen, is onderbroken. In dit geval gooit de methode een InterruptedException.

Tenslotte, als de thread waarnaar wordt verwezen al is beëindigd of nog niet is gestart, wordt de aanroep naar toetreden () methode keert onmiddellijk terug.

Thread t1 = nieuwe SampleThread (0); t1.join (); // keert onmiddellijk terug

3. Thread.join () Methoden met time-out

De toetreden () methode blijft wachten als de thread waarnaar wordt verwezen is geblokkeerd of te lang duurt om te verwerken. Dit kan een probleem worden omdat de aanroepende thread niet meer reageert. Om met deze situaties om te gaan, gebruiken we overbelaste versies van de toetreden () methode waarmee we een time-outperiode kunnen specificeren.

Er zijn twee getimede versies die het toetreden () methode:

"Openbare laatste leegte join (long millis) gooit InterruptedException

Wacht hoogstens millis milliseconden voordat deze draad sterft. Een time-out van 0 betekent voor altijd wachten. "

"Openbare laatste leegte join (long millis, intnanos) gooit InterruptedException

Wacht hoogstens millis milliseconden plus nanos nanoseconden voordat deze draad doodgaat. "

We kunnen de getimede gebruiken toetreden () zoals hieronder:

@Test openbare leegte gegevenStartedThread_whenTimedJoinCalled_waitsUntilTimedout () gooit InterruptedException {Thread t3 = nieuwe SampleThread (10); t3.start (); t3.join (1000); assertTrue (t3.isAlive ()); } 

In dit geval wacht de aanroepende thread ongeveer 1 seconde totdat de thread t3 is voltooid. Als de thread t3 in deze periode niet eindigt, wordt de toetreden () methode geeft de controle terug naar de aanroepende methode.

Getimed toetreden () is afhankelijk van het besturingssysteem voor timing. Dat kunnen we dus niet aannemen toetreden () wacht precies zo lang als gespecificeerd.

4. Thread.join () Methoden en synchronisatie

Naast het wachten tot de beëindiging, belt u het toetreden () methode heeft een synchronisatie-effect. join () creëert een 'gebeurt-voordat'-relatie:

"Alle acties in een thread vinden plaats voordat een andere thread met succes terugkeert van een join () op die thread."

Dit betekent dat wanneer een thread t1 t2.join () aanroept, alle wijzigingen die door t2 zijn aangebracht bij terugkeer zichtbaar zijn in t1. Als we echter geen beroep doen toetreden () of andere synchronisatiemechanismen gebruiken, hebben we geen enkele garantie dat wijzigingen in de andere thread zichtbaar zullen zijn voor de huidige thread, zelfs als de andere thread is voltooid.

Vandaar, hoewel de toetreden () method-aanroep naar een thread in de beëindigde status keert onmiddellijk terug, we moeten het in sommige situaties nog steeds aanroepen.

We kunnen hieronder een voorbeeld zien van onjuist gesynchroniseerde code:

SampleThread t4 = nieuwe SampleThread (10); t4.start (); // stopt niet gegarandeerd, zelfs als t4 is afgelopen. do {} while (t4.processingCount> 0);

Om bovenstaande code goed te synchroniseren, kunnen we getimed toevoegen t4.join () binnen de lus of gebruik een ander synchronisatiemechanisme.

5. Conclusie

toetreden () methode is erg handig voor synchronisatie tussen threads. In dit artikel hebben we de toetreden () methoden en hun gedrag. We hebben ook de code met behulp van toetreden () methode.

Zoals altijd is de volledige broncode te vinden op GitHub.