並發工具類

概述

Java 提供了多種並發工具類,用於協調多個執行緒之間的同步操作。

Semaphore 信號量

Semaphore 是一種用於控制多個執行緒同時訪問共享資源的同步機制。它可以限制同時訪問的執行緒數量。

Semaphore

Semaphore 提供了兩個操作:acquire(獲取)和 release(釋放)。當一個執行緒要訪問共享資源時,它需要先獲取信號量,如果信號量可用則獲取成功,否則它會被阻塞直到有其他執行緒釋放了信號量。
SemaphoreExample.java
Semaphore semaphore = new Semaphore(3); // 最多允許 3 個執行緒同時訪問

// 獲取許可
semaphore.acquire();
try {
    // 訪問共享資源
} finally {
    // 釋放許可
    semaphore.release();
}

CountDownLatch 倒數門檻

CountDownLatch 是一種同步工具,它允許一個或多個執行緒等待直到其他一組執行緒完成它們的操作。

CountDownLatch

CountDownLatch 包含一個計數器,當計數器值為零時,等待的執行緒將被釋放。每當一個執行緒完成其工作時,它會將計數器減少一個數量。
CountDownLatchExample.java
CountDownLatch latch = new CountDownLatch(3);

// 工作執行緒
for (int i = 0; i < 3; i++) {
    new Thread(() -> {
        // 執行工作
        System.out.println(Thread.currentThread().getName() + " 完成工作");
        latch.countDown(); // 計數器減 1
    }).start();
}

// 主執行緒等待
latch.await(); // 等待計數器歸零
System.out.println("所有工作完成");

CyclicBarrier 循環屏障

CyclicBarrier 允許一組執行緒在特定的屏障點同步等待彼此,然後在所有執行緒都到達後繼續執行。

CyclicBarrier

CyclicBarrier 可以重複使用,一旦所有執行緒都到達屏障點,它會重置以便下一次使用。
CyclicBarrierExample.java
CyclicBarrier barrier = new CyclicBarrier(3, () -> {
    System.out.println("所有執行緒都到達屏障點");
});

for (int i = 0; i < 3; i++) {
    new Thread(() -> {
        System.out.println(Thread.currentThread().getName() + " 到達屏障");
        try {
            barrier.await(); // 等待其他執行緒
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " 繼續執行");
    }).start();
}

CountDownLatch vs CyclicBarrier

特性CountDownLatchCyclicBarrier
重複使用不可以可以
計數方式倒數至零等待所有執行緒到達
用途等待一組事件完成執行緒間相互等待

Exchanger 交換器

Exchanger 用於兩個執行緒之間交換資料的同步點。每個執行緒在 Exchanger 點上等待,直到另一個執行緒也到達,然後它們交換資料後繼續執行。

Exchanger

ExchangerExample.java
Exchanger<String> exchanger = new Exchanger<>();

new Thread(() -> {
    try {
        String data = "資料 A";
        String received = exchanger.exchange(data);
        System.out.println("執行緒 1 收到: " + received);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}).start();

new Thread(() -> {
    try {
        String data = "資料 B";
        String received = exchanger.exchange(data);
        System.out.println("執行緒 2 收到: " + received);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}).start();

Phaser 階段器

Phaser 提供了一種更靈活的同步機制,用於控制多階段執行的同步。它可以用於同步執行緒在多個階段之間的協調。

Phaser

每個階段都可以包含任意數量的執行緒,並且當所有執行緒完成該階段時,才能進入下一個階段。Phaser 比 CyclicBarrier 更靈活,因為可以動態註冊和取消註冊參與者。
PhaserExample.java
Phaser phaser = new Phaser(3); // 3 個參與者

for (int i = 0; i < 3; i++) {
    new Thread(() -> {
        System.out.println(Thread.currentThread().getName() + " 階段 1 完成");
        phaser.arriveAndAwaitAdvance(); // 等待其他執行緒完成階段 1

        System.out.println(Thread.currentThread().getName() + " 階段 2 完成");
        phaser.arriveAndAwaitAdvance(); // 等待其他執行緒完成階段 2

        System.out.println(Thread.currentThread().getName() + " 所有階段完成");
        phaser.arriveAndDeregister(); // 完成並取消註冊
    }).start();
}

總結比較

工具類用途重複使用動態參與者
Semaphore限制同時訪問資源的執行緒數-
CountDownLatch等待一組事件完成
CyclicBarrier執行緒間相互等待
Exchanger兩執行緒間交換資料-
Phaser多階段同步

參考資源