La méthode Thread.join () en Java

La méthode Thread.join () en Java

 

1. Vue d'ensemble

Dans ce didacticiel, nous aborderons les différentes méthodesjoin() de la classeThread. Nous allons entrer dans les détails de ces méthodes et quelques exemples de code.

Comme leswait() etnotify() methods,join() est un autre mécanisme de synchronisation inter-thread.

Vous pouvez jeter un coup d'œil surthis tutorial pour en savoir plus surwait() etnotify().

2. La méthodeThread.join()

La méthode de jointure est définie dans la classeThread:

public final void join () jette une exception InterruptedException Attend que ce fil meure.

Lorsque nous appelons la méthodejoin() sur un thread, le thread appelant passe dans un état d'attente. Il reste dans un état d'attente jusqu'à ce que le thread référencé se termine.

Nous pouvons voir ce comportement dans le code suivant:

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());
}

Nous devrions nous attendre à des résultats similaires à ceux-ci lors de l'exécution du code:

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

The join() method may also return if the referenced thread was interrupted. Dans ce cas, la méthode renvoie unInterruptedException.

Enfin,if the referenced thread was already terminated or hasn’t been started, the call to join() method returns immediately.

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

3. Thread.join() Méthodes avec timeout

La méthodejoin() continuera à attendre si le thread référencé est bloqué ou prend trop de temps à traiter. Cela peut devenir un problème car le thread appelant ne répond plus. Pour gérer ces situations, nous utilisons des versions surchargées de la méthodejoin() qui nous permettent de spécifier un délai d'expiration.

Il y a deuxtimed versions qui surchargent la méthodejoin():

“public final void join(long millis_) lance InterruptedException_Waits at most millis milliseconds for this thread to die. A timeout of 0 means to wait forever.”

“public final void join(long millis, int nanos_) lance InterruptedException_Waits at most millis milliseconds plus nanos_ nanosecondes pour que ce thread meure. »_

Nous pouvons utiliser lesjoin() chronométrés comme ci-dessous:

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

Dans ce cas, le thread appelant attend environ 1 seconde que le thread t3 se termine. Si le thread t3 ne se termine pas dans cette période, la méthodejoin() renvoie le contrôle à la méthode appelante.

Timedjoin() dépend du système d'exploitation pour la synchronisation. Donc, nous ne pouvons pas supposer quejoin() attendra exactement aussi longtemps que spécifié.

4. Thread.join() Méthodes et synchronisation

En plus d'attendre la fin, l'appel de la méthodejoin() a un effet de synchronisation. join() creates a happens-before relationship:

"Toutes les actions d'un thread se produisent avant que tout autre thread ne retourne avec succès d'une jointure () sur ce thread."

Cela signifie que lorsqu'un thread t1 appelle t2.join (), toutes les modifications effectuées par t2 sont visibles dans t1 au retour. Cependant, si nous n'appelons pasjoin() ou n'utilisons pas d'autres mécanismes de synchronisation, nous n'avons aucune garantie que les changements dans l'autre thread seront visibles par le thread actuel même si l'autre thread est terminé.

Par conséquent, même si l'appel de la méthodejoin() à un thread dans l'état terminé retourne immédiatement, nous devons toujours l'appeler dans certaines situations.

Nous pouvons voir un exemple de code mal synchronisé ci-dessous:

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

} while (t4.processingCount > 0);

Pour synchroniser correctement le code ci-dessus, nous pouvons ajouter dest4.join() chronométrés dans la boucle ou utiliser un autre mécanisme de synchronisation.

5. Conclusion

La méthodejoin() est assez utile pour la synchronisation inter-thread. Dans cet article, nous avons discuté des méthodesjoin() et de leur comportement. Nous avons également examiné le code en utilisant la méthodejoin().

Comme toujours, le code source complet peut être trouvéover on GitHub.