概述
字面意思迴環柵欄,通過它可以實現讓一組線程等待至某個狀態之後再全部同時執行。叫做迴環是因爲當所有等待線程都被釋放以後,CyclicBarrier可以被重用。我們暫且把這個狀態就叫做barrier,當調用await()方法之後,線程就處於barrier了。
package com.business.thread;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CyclicBarrier;
public class UseCyclicBarrier {
static CyclicBarrier barrier = new CyclicBarrier(5, new collectThread());
private static ConcurrentHashMap<String, Long> resultMap = new ConcurrentHashMap<String, Long>();// 存放子線程工作結果的容器
public static void main(String[] args) {
for (int i = 0; i <= 4; i++) {
Thread thread = new Thread(new SubThread());
thread.start();
}
}
// 彙總線程
private static class collectThread implements Runnable {
public void run() {
StringBuilder result = new StringBuilder();
for (Map.Entry<String, Long> workResult : resultMap.entrySet()) {
result.append("[" + workResult.getValue() + "]");
}
System.out.println("result :" + result);
System.out.println("do other business");
}
}
// 工作線程
private static class SubThread implements Runnable {
public void run() {
long id = Thread.currentThread().getId();
resultMap.put(id + "", id);
Random r = new Random();
if (r.nextBoolean()) {
try {
Thread.sleep((int) (1000 + id));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Thread_" + id + "......do sth");
}
try {
//等待collectThread線程完成
barrier.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
Thread.sleep((int) (1000 + id));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Thread_" + id + "............do business");
}
}
}
執行結果:
Thread_13......do sth
result :[11][12][13][14][10]
do other business
Thread_10............do business
Thread_11............do business
Thread_12............do business
Thread_13............do business
Thread_14............do business
SubThread線程需要等待collectThread線程完成之後,才能繼續下面的任務。
CyclicBarrier與CountDownLatch比較
1)CountDownLatch:一個線程(或者多個),等待另外N個線程完成某個事情之後才能執行;CyclicBarrier:N個線程相互等待,任何一個線程完成之前,所有的線程都必須等待。
2)CountDownLatch:一次性的;CyclicBarrier:可以重複使用。
3)CountDownLatch基於AQS;CyclicBarrier基於鎖和Condition。本質上都是依賴於volatile和CAS實現的。