在并發(fā)工具類中,我們簡(jiǎn)單了解了CyclicBarrier菊碟,接下來走讀下代碼看看其是如何實(shí)現(xiàn)的,代碼基于JDK1.7。
代碼走讀
從上圖可以看出CyclicBarrier是基于可重入鎖的條件隊(duì)列實(shí)現(xiàn)的飞盆,parties代表同一代的線程數(shù),count代表同一代等待的線程數(shù)次乓,調(diào)用await()方法一次吓歇,count減1,直到為0票腰。接下來看看dowait()方法(await()方法其實(shí)調(diào)用dowait()方法)城看。這個(gè)是CyclicBarrier最核心的方法。
柵欄破壞丧慈,拋出異常析命。
線程中斷主卫,主要看breakBarrier()方法,這個(gè)方法也很重要鹃愤。
同一代等待的線程數(shù)減1.
當(dāng)同一代等待的線程數(shù)為0時(shí)簇搅,首先執(zhí)行barrierCommand的run()方法,注意:等待的線程沒有執(zhí)行软吐。
當(dāng)同一代等待的線程數(shù)為0時(shí)瘩将,調(diào)用nextGeneration()方法。
喚醒等待的線程凹耙,即CyclicBarrier的線程中斷后姿现,等待的線程還是要執(zhí)行的。
喚醒等待的線程肖抱,即首先執(zhí)行barrierCommand的run()方法备典,然后等待的線程執(zhí)行;同時(shí)new Generation()意述,即產(chǎn)生新的一代提佣,這里可以看出復(fù)用。
線程添加到循環(huán)隊(duì)列荤崇。
出現(xiàn)異常后執(zhí)行喚醒等待線程繼續(xù)執(zhí)行拌屏,即:超時(shí)后barrierCommand的run()方法不執(zhí)行,等待線程仍然執(zhí)行术荤。
總結(jié):CyclicBarrier基于可重入鎖的條件隊(duì)列實(shí)現(xiàn)的倚喂,可以復(fù)用的柵欄。
例子
public class CyclicBarrierDemo {
private static int SIZE = 5;
private static CyclicBarrier cb;
public static void main(String[] args) {
cb = new CyclicBarrier(SIZE, new Runnable() {
public void run() {
System.out.println("CyclicBarrier's parties is: " + cb.getParties());
}
});
// 新建10個(gè)任務(wù)
for (int i = 0; i < 10; i++)
new InnerThread().start();
}
static class InnerThread extends Thread {
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " wait for CyclicBarrier.");
// 將cb的參與者數(shù)量加1
cb.await();
// cb的參與者數(shù)量等于5時(shí)瓣戚,才繼續(xù)往后執(zhí)行
System.out.println(Thread.currentThread().getName() + " continued.");
} catch (BrokenBarrierException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//執(zhí)行結(jié)果
Thread-0 wait for CyclicBarrier.
Thread-1 wait for CyclicBarrier.
Thread-2 wait for CyclicBarrier.
Thread-3 wait for CyclicBarrier.
Thread-4 wait for CyclicBarrier.
CyclicBarrier's parties is: 5
Thread-5 wait for CyclicBarrier.
Thread-4 continued.
Thread-0 continued.
Thread-3 continued.
Thread-2 continued.
Thread-1 continued.
Thread-6 wait for CyclicBarrier.
Thread-7 wait for CyclicBarrier.
Thread-8 wait for CyclicBarrier.
Thread-9 wait for CyclicBarrier.
CyclicBarrier's parties is: 5
Thread-9 continued.
Thread-5 continued.
Thread-7 continued.
Thread-8 continued.
Thread-6 continued.