Utilisation de CountDownLatch pour la Synchronisation des Threads en Java

La classe CountDownLatch dans le package java.util.concurrent focntionne comme un compteur atomique pour coordonner les threads. Un seul thread peut modifier la valeur à la fois, garantissant une sécurité contre les conditions de course.

Vous définissez une valeur initiale pour ce compteur. Toute invocation de la méthode await() sur l'objet CountDownLatch bloque le thread appelant jusqu'à ce que le compteur soit décrémenté à zéro par d'autres threads via la méthode countDown().

Ce mécanisme est utile lorsqu'un thread doit attendre l'achèvement d'un ensemble de tâches parallèles avant de cotninuer. Par exemple, un gestionnaire qui attend que tous les employés finissent leurs tâches pour démarrer une revue de qualité.

Considérons un scénario avec trois employés et un gestionnaire. Les classes suivantes illustrent cette synchronisation :

import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit;

public class Employe implements Runnable { private final CountDownLatch compteurLatch; private final String identifiant;

public Employe(CountDownLatch latch, String id) {
    this.compteurLatch = latch;
    this.identifiant = id;
}

@Override
public void run() {
    executerTache();
    try {
        TimeUnit.SECONDS.sleep(new Random().nextInt(10));
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
    System.out.println(identifiant + " a terminé son travail!");
    compteurLatch.countDown();
}

private void executerTache() {
    System.out.println(identifiant + " est en train de travailler.");
}

}


</div><div>```
package fr.example.concurrent;

import java.util.concurrent.CountDownLatch;

public class Gestionnaire implements Runnable {
    private final CountDownLatch compteurLatch;

    public Gestionnaire(CountDownLatch latch) {
        this.compteurLatch = latch;
    }

    @Override
    public void run() {
        System.out.println("Le gestionnaire attend que tous les employés finissent...");
        try {
            compteurLatch.await();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        System.out.println("Tous les employés ont fini, le gestionnaire commence la revue!");
    }
}

import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;

public class DemoCountDownLatch { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); CountDownLatch latch = new CountDownLatch(3);

    Employe emp1 = new Employe(latch, "Alice");
    Employe emp2 = new Employe(latch, "Bob");
    Employe emp3 = new Employe(latch, "Charlie");
    Gestionnaire gestionnaire = new Gestionnaire(latch);

    service.execute(emp3);
    service.execute(emp2);
    service.execute(emp1);
    service.execute(gestionnaire);
    service.shutdown();
}

}


</div>Lors de l'exécution, le gestionnaire reste bloqué jusqu'à ce que les trois employés aient terminé. Une sortie possible est :

<div>```
Charlie est en train de travailler.
Bob est en train de travailler.
Le gestionnaire attend que tous les employés finissent...
Alice est en train de travailler.
Alice a terminé son travail!
Charlie a terminé son travail!
Bob a terminé son travail!
Tous les employés ont fini, le gestionnaire commence la revue!

Étiquettes: Java CountDownLatch Concurrence multithreading synchronisation

Publié le 6 juin à 20h14