CyclicBarrieer JUC 下的 一个并发同步工具类 , 有翻译将其称之为 屏障器,它适用于这样一种情况,你希望创建一组任务,他们并发地执行当前的一组任务,另外的一个任务在这组任务并发执行结束前一直阻塞等待,直到该组任务全部执行结束,这个任务才得以执行,和 CountDownLatch 非常像,只是 CountDownLatch 是只触发一次它的计数器就失效了,而 CyclicBarrier 的计数器可以重用
来看一段代码实例
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierTest {
public static void main(String[] args) {
//创建CyclicBarrier对象,
//并设置执行完一组5个线程的并发任务后,再执行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();
}
}
/**
* 最后执行的任务
*/
class MainTask implements Runnable {
public void run() {
System.out.println("......终于要执行最后的任务了......");
}
}
/**
* 一组并发任务
*/
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("[并发任务" + name + "] 开始执行");
for (int i = 0; i < 999999; i++) ; //模拟耗时的任务
System.out.println("[并发任务" + name + "] 开始执行完毕,通知障碍器");
try {
//每执行完一项任务就通知障碍器
cb.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
执行结果如下。
可以看出 MainTask 是等 ABCDE 这 5 个 SubTask 执行完毕才执行的。
CountDownLatch 和 CyclicBarrier 的区别
CountDownLatch
有时候被称为 闭锁
,其作用就相当于 一扇门,在 CountDownLatch
达到结束状态之前,这扇门一直都是关闭的,并且没有任何线程能通过,当到达结束状态时,这扇门就会允许所有的线程通过,当CountDownLatch
到达结束状态后,将不会再改变状态,因此这扇门就永远保持打开状态。CountDownLatch
可以用来确保某些任务直到其他任务都完成后才继续执行。一个或者多个线程等待其他线程
CyclicBarrier
有称之为 障碍器,也有称之为栅栏,作用 和 CountDownLatch 非常相似,它能阻塞一组线程直到某个事件发生,关键的区别,关键的区别,关键的区别在于,CyclicBarrier 是一组线程互相等待的这么一个关系,比如公司组织去春游踏青,总共有 20 人去,大家定于周六早上8点集合,有的人 7:30 分就到了,有的同事是7:45 分就到了,有的人刚好 8:00 就到了,也有的人可能 8 :10 才到,大家到了集合地点之后呢,告诉小导游一句 xx 已到 ,相当于 CyclicBarrier.await() 。但是在整个个团队出发之前呢,每个成员都是在互相等待,等待其他成员,等其他成员都到了,小导游这里统计到人数实际为 20 人,好了大家都到了,准备出发踏青(准备开始下一个任务)。这个举例不一定很准确,但是 基本可以形象解释了CyclicBarrier ,那就是它等待的这些线程都必须都到达栅栏位置,才能继续进行,而CountDownLatch 用于等待事件,一个等事件,一个等其他线程
总结一下
CountDownLatch 不可重置,无法重用,CyclicBarrier 可以重用
CountDownLatch 的基本操作组合是 coutDown / await 。调用 await 的线程阻塞等待 countDown 足够的次数,不管你是在一个线程还是多个 线程里coutDown,只要次数足够就好,所以说 CountDownLatch 操作的是事件
CyclicBarrier 的基本组合是 await ,当所有的伙伴都调用了 await 才会继续执行任务,并自动重置,正常情况下,CyclicBarrier 的重置都是自动发生的,如果我们调用 reset 方法,但还有线程在等待,就会导致线程被打扰,抛出 BrokenBarrierException 异常,CyclicBarrier 侧重的是线程,而不是调用事件,他的典型应用场景是等待并发线程结束
http://www.importnew.com/20873.html
https://blog.csdn.net/qweqwruio/article/details/81359780