概述
字面意思回环栅栏,通过它可以实现让一组线程等待至某个状态之后再全部同时执行。叫做回环是因为当所有等待线程都被释放以后,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实现的。