鍍金池/ 教程/ Java/ 并發(fā)新特性—障礙器 CyclicBarrier
并發(fā)新特性—信號量 Semaphore
線程間協(xié)作:wait、notify、notifyAll
notify 通知的遺漏
notifyAll 造成的早期通知問題
多線程的實現(xiàn)方法
深入 Java 內存模型(1)
多線程環(huán)境下安全使用集合 API
并發(fā)新特性—Lock 鎖與條件變量
生產(chǎn)者—消費者模型
深入 Java 內存模型(2)
線程中斷
Volatile 關鍵字(上)
并發(fā)新特性—阻塞隊列與阻塞棧
可重入內置鎖
守護線程與線程阻塞
并發(fā)新特性—障礙器 CyclicBarrier
Volatile 關鍵字(下)
synchronized 關鍵字
synchronized 的另個一重要作用:內存可見性
并發(fā)新特性—Executor 框架與線程池
并發(fā)性與多線程介紹
死鎖
實現(xiàn)內存可見性的兩種方法比較:synchronized 和 Volatile
線程掛起、恢復與終止

并發(fā)新特性—障礙器 CyclicBarrier

CyclicBarrier(又叫障礙器)同樣是 Java 5 中加入的新特性,使用時需要導入java.util.concurrent.CylicBarrier。它適用于這樣一種情況:你希望創(chuàng)建一組任務,它們并發(fā)地執(zhí)行工作,另外的一個任務在這一組任務并發(fā)執(zhí)行結束前一直阻塞等待,直到該組任務全部執(zhí)行結束,這個任務才得以執(zhí)行。這非常像 CountDownLatch,只是 CountDownLatch 是只觸發(fā)一次的事件,而 CyclicBarrier 可以多次重用。

下面給出一個簡單的實例來說明其用法:

import java.util.concurrent.BrokenBarrierException;   
import java.util.concurrent.CyclicBarrier;   

public class CyclicBarrierTest {   
        public static void main(String[] args) {   
                //創(chuàng)建CyclicBarrier對象,  
                //并設置執(zhí)行完一組5個線程的并發(fā)任務后,再執(zhí)行MainTask任務  
                CyclicBarrier cb = new CyclicBarrier(5, new MainTask());   
                new SubTask("A", cb).start();   
                new SubTask("B", cb).start();   
                new SubTask("C", cb).start();   
                new SubTask("D", cb).start();   
                new SubTask("E", cb).start();  
        }   
}   

/**  
* 最后執(zhí)行的任務 
*/   
class MainTask implements Runnable {   
        public void run() {   
                System.out.println("......終于要執(zhí)行最后的任務了......");   
        }   
}   

/**  
* 一組并發(fā)任務  
*/   
class SubTask extends Thread {   
        private String name;   
        private CyclicBarrier cb;   

        SubTask(String name, CyclicBarrier cb) {   
                this.name = name;   
                this.cb = cb;   
        }   

        public void run() {   
                System.out.println("[并發(fā)任務" + name + "]  開始執(zhí)行");   
                for (int i = 0; i < 999999; i++) ;    //模擬耗時的任務   
                System.out.println("[并發(fā)任務" + name + "]  開始執(zhí)行完畢,通知障礙器");   
                try {   
                        //每執(zhí)行完一項任務就通知障礙器   
                        cb.await();   
                } catch (InterruptedException e) {   
                        e.printStackTrace();   
                } catch (BrokenBarrierException e) {   
                        e.printStackTrace();   
                }   
        }   
}  

某次執(zhí)行的結果如下:

[并發(fā)任務A]  開始執(zhí)行
[并發(fā)任務B]  開始執(zhí)行
[并發(fā)任務D]  開始執(zhí)行
[并發(fā)任務E]  開始執(zhí)行
[并發(fā)任務A]  開始執(zhí)行完畢,通知障礙器
[并發(fā)任務E]  開始執(zhí)行完畢,通知障礙器
[并發(fā)任務D]  開始執(zhí)行完畢,通知障礙器
[并發(fā)任務C]  開始執(zhí)行
[并發(fā)任務B]  開始執(zhí)行完畢,通知障礙器
[并發(fā)任務C]  開始執(zhí)行完畢,通知障礙器
......終于要執(zhí)行最后的任務了......

從結果可以看出:MainTask 任務在一組中的 5 個任務執(zhí)行完后才開始執(zhí)行。