Maison >Java >javaDidacticiel >Exemples de code pour les synchroniseurs
Voici des exemples de codes pour les synchroniseurs mentionnés au point 80, avec des explications d'utilisation pour faciliter l'étude :
1. CountDownLatch : barrière à usage unique pour la coordination des threads
CountDownLatch permet à un ou plusieurs threads d'attendre qu'un ensemble d'opérations effectuées par d'autres threads soit terminé.
import java.util.concurrent.CountDownLatch; public class CountDownLatchExample { public static void main(String[] args) throws InterruptedException { int numberOfWorkers = 3; CountDownLatch latch = new CountDownLatch(numberOfWorkers); for (int i = 0; i < numberOfWorkers; i++) { new Thread(new Worker(latch, "Worker-" + i)).start(); } System.out.println("Waiting for workers to finish..."); latch.await(); // Aguarda todos os trabalhadores chamarem latch.countDown() System.out.println("All workers are done. Proceeding..."); } static class Worker implements Runnable { private final CountDownLatch latch; private final String name; Worker(CountDownLatch latch, String name) { this.latch = latch; this.name = name; } @Override public void run() { System.out.println(name + " is working..."); try { Thread.sleep((long) (Math.random() * 2000)); // Simula trabalho } catch (InterruptedException e) { Thread.currentThread().interrupt(); } System.out.println(name + " finished."); latch.countDown(); // Decrementa o contador } } }
2. Sémaphore : Contrôler l'accès aux ressources partagées
Semaphore gère un ensemble d'autorisations pour contrôler l'accès à des ressources limitées.
import java.util.concurrent.Semaphore; public class SemaphoreExample { public static void main(String[] args) { int permits = 2; // Número de permissões disponíveis Semaphore semaphore = new Semaphore(permits); for (int i = 1; i <= 5; i++) { new Thread(new Task(semaphore, "Task-" + i)).start(); } } static class Task implements Runnable { private final Semaphore semaphore; private final String name; Task(Semaphore semaphore, String name) { this.semaphore = semaphore; this.name = name; } @Override public void run() { try { System.out.println(name + " is waiting for a permit..."); semaphore.acquire(); // Adquire uma permissão System.out.println(name + " got a permit and is working..."); Thread.sleep((long) (Math.random() * 2000)); // Simula trabalho System.out.println(name + " is releasing a permit."); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { semaphore.release(); // Libera a permissão } } } }
3. CyclicBarrier : Synchronisation sur points barrières réutilisables
CyclicBarrier synchronise plusieurs threads en un point commun (barrière). Il peut être réutilisé une fois que tous les fils ont atteint le point barrière.
import java.util.concurrent.CyclicBarrier; public class CyclicBarrierExample { public static void main(String[] args) { int numberOfThreads = 3; CyclicBarrier barrier = new CyclicBarrier(numberOfThreads, () -> { System.out.println("All threads have reached the barrier. Proceeding..."); }); for (int i = 0; i < numberOfThreads; i++) { new Thread(new Task(barrier, "Thread-" + i)).start(); } } static class Task implements Runnable { private final CyclicBarrier barrier; private final String name; Task(CyclicBarrier barrier, String name) { this.barrier = barrier; this.name = name; } @Override public void run() { try { System.out.println(name + " is performing some work..."); Thread.sleep((long) (Math.random() * 2000)); // Simula trabalho System.out.println(name + " reached the barrier."); barrier.await(); // Aguarda todas as threads chegarem à barreira System.out.println(name + " passed the barrier."); } catch (Exception e) { Thread.currentThread().interrupt(); } } } }
4. Phaser : Synchronisation avancée et dynamique des threads
Phaser est similaire à CyclicBarrier, mais prend en charge l'entrée et la sortie dynamiques des threads.
import java.util.concurrent.Phaser; public class PhaserExample { public static void main(String[] args) { Phaser phaser = new Phaser(1); // Registra o "partida principal" for (int i = 0; i < 3; i++) { new Thread(new Task(phaser, "Task-" + i)).start(); } // Avança para a próxima fase após garantir que todas as threads registradas concluíram System.out.println("Main thread waiting for phase 1 completion..."); phaser.arriveAndAwaitAdvance(); System.out.println("All tasks completed phase 1. Main thread moving to phase 2..."); phaser.arriveAndDeregister(); // Desregistra a thread principal } static class Task implements Runnable { private final Phaser phaser; private final String name; Task(Phaser phaser, String name) { this.phaser = phaser; this.name = name; phaser.register(); // Registra a thread no Phaser } @Override public void run() { System.out.println(name + " is working on phase 1..."); try { Thread.sleep((long) (Math.random() * 2000)); // Simula trabalho } catch (InterruptedException e) { Thread.currentThread().interrupt(); } System.out.println(name + " completed phase 1."); phaser.arriveAndAwaitAdvance(); // Indica chegada na fase atual e aguarda System.out.println(name + " is working on phase 2..."); try { Thread.sleep((long) (Math.random() * 2000)); // Simula trabalho } catch (InterruptedException e) { Thread.currentThread().interrupt(); } System.out.println(name + " completed phase 2."); phaser.arriveAndDeregister(); // Indica chegada e desregistra } } }
Ces exemples vous aident à comprendre le fonctionnement de chaque synchroniseur. Vous pouvez expérimenter en ajustant les numéros de thread et les timings pour observer les effets sur le comportement de synchronisation.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!