柵欄類似於閉鎖,它能阻塞一組線程直到某個事件的發生。柵欄與閉鎖的關鍵區別在於,所有的線程必須同時到達柵欄位置,才能繼續執行。閉鎖用於等待事件,而柵欄用於等待其他線程。
Cyclic Barrer也可以用於解決多個線程之間的相互等待問題。Cyclic Barrier的使用場景是, 每個線程在執行時, 都會碰到屏障, 該屏障會攔截所有線程的執行(通過await() 方法實現) ;當指定數量的線程全部就位時,所有的線程再跨過屏障同時執行。
現舉例說明CountDown Latch和Cyclic Barrier的區別。假設有A、B、C 3個線程, 其中C是最後一個加人的線程。(1) 使用CountDown Latch, 可以實現當A和B全部執行完畢後, C再去執行。(2) 使用Cyclic Barrier,可以實現A、B等到C就緒後(await O) 表示就緒) , A、B、C三者再同時去執行。範例4-7線程屏障3個人去開會,只有當3個人都抵達之後,會議才開始。換句話說,當最後一個人抵達後,會議就開始。
代碼如下:
package com.highcon.thread;
import java.io.IOException;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestCyclicBarrier {
static class MyThread implements Runnable {
//用於控制會議開始的屏障
private CyclicBarrier barrier;
//參會人員
private String person;
public MyThread(CyclicBarrier barrier, String name) {
this.barrier = barrier;
this.person = name;
}
public void run() {
try {
Thread.sleep((int) (10000 * Math.random()));
System.out.println(person + " 已經到會...");
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(person + " 開始會議...");
}
}
public static void main(String[] args) throws IOException, InterruptedException {
//將屏障設置為3,即當有3個線程執行到await()時,再同時釋放
CyclicBarrier barrier = new CyclicBarrier(3);
ExecutorService executor = Executors.newFixedThreadPool(3);
//三個人去開會
executor.submit(new MyThread(barrier, "zs"));
executor.submit(new MyThread(barrier, "ls"));
executor.submit(new MyThread(barrier, "ww"));
executor.shutdown();
}
}
運行結果如下圖: