Here are code examples for the synchronizers mentioned in item 80, with explanations of use to facilitate the study:
1. CountDownLatch: Single-use barrier for thread coordination
CountDownLatch allows one or more threads to wait until a set of operations performed by other threads is completed.
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. Semaphore: Control access to shared resources
Semaphore manages a set of permissions to control access to limited resources.
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: Synchronization on reusable barrier points
CyclicBarrier synchronizes multiple threads at a common point (barrier). It can be reused after all threads reach the barrier point.
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: Advanced and dynamic thread synchronization
Phaser is similar to CyclicBarrier, but supports dynamically entering and leaving 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 } } }
These examples help you understand how each synchronizer works. You can experiment by adjusting the thread numbers and timings to observe the effects on the synchronization behavior.
The above is the detailed content of Code examples for the synchronizers. For more information, please follow other related articles on the PHP Chinese website!