Implémentation de deux threads pour imprimer alternativement les nombres de 1 à 100 en Java

Dans ce scénario, nous devons développer deux threads qui impriment alternativement les nombres de 1 à 100, l'un dédié aux nombres impairs et l'autre aux nombres pairs. Plusieurs techniques de synchronisation sont applicables, comme les mécanismes wait/notify ou les sémaphores.

Approche avec synchronized et wait/notify

Une classe AlternatingPrinter est définie pour gérer l'impression. Elle utilise un verou pour coordonner l'exécution des threads.


public class AlternatingPrinter {
    private final int upperLimit;
    private int currentNumber = 1;
    private final Object mutex = new Object();

    public AlternatingPrinter(int upperLimit) {
        this.upperLimit = upperLimit;
    }

    public void printOdd() {
        generateOutput(true);
    }

    public void printEven() {
        generateOutput(false);
    }

    private void generateOutput(boolean isOddThread) {
        for (int step = 0; step < upperLimit / 2; step++) {
            synchronized (mutex) {
                while (isOddThread == (currentNumber % 2 == 0)) {
                    try {
                        mutex.wait();
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        return;
                    }
                }
                System.out.println(Thread.currentThread().getName() + " : " + currentNumber++);
                mutex.notify();
            }
        }
    }
}

Ensuite, les threads sont créés et démarrés pour imprimer les nombres impairs et pairs.


AlternatingPrinter printer = new AlternatingPrinter(100);
Thread oddThread = new Thread(printer::printOdd, "Impair");
Thread evenThread = new Thread(printer::printEven, "Pair");
oddThread.start();
evenThread.start();

La sortie résultante respecte l'alternance :


Impair : 1
Pair : 2
Impair : 3
Pair : 4
...
Impair : 99
Pair : 100

Approche avec Sémaphores

Une implémentation alternative utilise des sémaphores pour contrôler l'accès. Chaque thread gère un sémaphore pour signaler le suivant.


public class AlternatingPrinter {
    private final int limit;
    private int count = 1;
    private final Semaphore oddSemaphore = new Semaphore(1);
    private final Semaphore evenSemaphore = new Semaphore(0);

    public AlternatingPrinter(int limit) {
        this.limit = limit;
    }

    public void printOdd() {
        alternate(oddSemaphore, evenSemaphore);
    }

    public void printEven() {
        alternate(evenSemaphore, oddSemaphore);
    }

    private void alternate(Semaphore current, Semaphore next) {
        for (int i = 0; i < limit / 2; i++) {
            try {
                current.acquire();
                System.out.println(Thread.currentThread().getName() + " : " + count++);
                next.release();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return;
            }
        }
    }
}

Cette méthode assure une exécution séquentielle sans verrou explicite, en utilisant l'état initial des sémaphores pour démarrer avec le thread impair.

Étiquettes: Java multithreading Synchronization Semaphore Thread Communication

Publié le 3 juin à 00h03