博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
倒计时器CountDownLatch与同步屏障CyclicBarrier
阅读量:4606 次
发布时间:2019-06-09

本文共 3646 字,大约阅读时间需要 12 分钟。

CountDownLatch

CountDownLatch是一个非常实用的多线程控制工具类,这个工具通常用来控制线程等待,它可以让某一个线程等待直到倒计时结束,再开始执行。在这里指CountDownLatch.await()方法在倒计数为0之前会阻塞程序运行。

CountDownLatch 的作用和 Thread.join() 方法类似,可用于一组线程和另外一组线程的协作。例如,主线程在做一项工作之前需要一系列的准备工作,只有这些准备工作都完成,主线程才能继续它的工作。这些准备工作彼此独立,所以可以并发执行以提高速度。在这个场景下就可以使用 CountDownLatch 协调线程之间的调度了。

CountDownLatch的构造函数接收一个整数作为参数,即当前这个计数器的计数个数。

下面我们看一个经典案例: 

 
public class CountDownLatchDemo implements Runnable{    static final CountDownLatch countDownLatch = new CountDownLatch(10);    @Override public void run() {        try {            Thread.sleep(new Random().nextInt(10)*1000);            System.out.println("Check complete!");            countDownLatch.countDown();        } catch (InterruptedException e) {            e.printStackTrace();        }    }    public static void main(String[] args) throws InterruptedException {        final CountDownLatchDemo demo = new CountDownLatchDemo();        ExecutorService exec = Executors.newFixedThreadPool(10);        for (int i = 0; i < 10; i++) {            exec.submit(demo);        }        countDownLatch.await();        System.out.println("发射火箭...Fire");        exec.shutdown();    }}
 

如代码所示:主线程一直在等待线程执行完反馈结果,直到我们定义的10个线程均执行成功且调用了countDown()方法,每次调用计数器减1,到0时会立即调用主函数"发射火箭…Fire"假设我们只循环9次,那么主线程就会一直等待。

CyclicBarrier  

CyclicBarrier是另外一种多线程并发控制实用工具。和CountDownLatch非常类似,它也可是实现线程间的计数等待。它主要的方法就是一个:await()。await() 方法每被调用一次,计数便会减少1,并阻塞住当前线程。当计数减至0时,阻塞解除,所有在此 CyclicBarrier 上面阻塞的线程开始运行。在这之后,如果再次调用 await() 方法,计数就又会变成 N-1,新一轮重新开始,这便是 Cyclic 的含义所在。

CyclicBarrier 的使用并不难,但需要主要它所相关的异常。除了常见的异常,CyclicBarrier.await() 方法会抛出一个独有的 BrokenBarrierException。这个异常发生在当某个线程在等待本 CyclicBarrier 时被中断或超时或被重置时,其它同样在这个 CyclicBarrier 上等待的线程便会受到 BrokenBarrierException。意思就是说,同志们,别等了,有个小伙伴已经挂了,咱们如果继续等有可能会一直等下去,所有各回各家吧。

案例:

public class CyclicBarrierDemo {    static class Runner implements Runnable {        private CyclicBarrier barrier;        private String name;        public Runner(CyclicBarrier barrier, String name) {            this.barrier = barrier;            this.name = name;        }        @Override        public void run() {            try {                Thread.sleep(1000 * (new Random()).nextInt(5));                System.out.println(name + " 准备OK.");                barrier.await();            } catch (InterruptedException e) {                e.printStackTrace();            } catch (BrokenBarrierException e) {                e.printStackTrace();            }            System.out.println(name + " Go!!");        }    }    public static void main(String[] args) throws IOException, InterruptedException {        CyclicBarrier barrier = new CyclicBarrier(3);  // 3        ExecutorService executor = Executors.newFixedThreadPool(3);        executor.submit(new Thread(new Runner(barrier, "zhangsan")));        executor.submit(new Thread(new Runner(barrier, "lisi")));        executor.submit(new Thread(new Runner(barrier, "wangwu")));        executor.shutdown();    }}

运动员准备完成以后需要等待其他运动员准备完成,所有的运动员准备完成后再一起执行System.out.println(name + " Go!!");方法。

CyclicBarrier 和 CountDownLatch 在用法上的不同

CountDownLatch 适用于一组线程和另一个主线程之间的工作协作。一个主线程等待一组工作线程的任务完毕才继续它的执行是使用 CountDownLatch 的主要场景;CyclicBarrier 用于一组或几组线程,比如一组线程需要在一个时间点上达成一致,例如同时开始一个工作。另外,CyclicBarrier 的循环特性和构造函数所接受的 Runnable 参数也是 CountDownLatch 所不具备的。

具体点:

 

CountDownLatch : 一个线程(或者多个), 等待另外N个线程完成某个事情之后才能执行。  

CyclicBarrier       : N个线程相互等待,任何一个线程完成之前,所有的线程都必须等待。

这样应该就清楚一点了,对于CountDownLatch来说,重点是那个“一个线程”, 是它在等待, 而另外那N的线程在把“某个事情”做完之后可以继续等待,可以终止。而对于CyclicBarrier来说,重点是那N个线程,他们之间任何一个没有完成,所有的线程都必须等待。 

 

CountDownLatch 是计数器, 线程完成一个就记一个, 就像 报数一样, 只不过是递减的.

 

而CyclicBarrier更像一个水闸, 线程执行就像水流, 在水闸处都会堵住, 等到水满(线程到齐)了, 才开始泄流.

 

转载于:https://www.cnblogs.com/jianzh5/p/6124425.html

你可能感兴趣的文章
BZOJ3675 [Apio2014]序列分割 动态规划 斜率优化
查看>>
Django extend(继承)模板标签
查看>>
2016.10.24 继续学习
查看>>
产品功能对标 - 服务授权管理
查看>>
各地IT薪资待遇讨论
查看>>
splay入门
查看>>
带CookieContainer进行post
查看>>
C语言学习笔记--字符串
查看>>
CSS-上下文选择器
查看>>
ionic repeat 重复最后一个时要执行某个函数
查看>>
1.初识代码审计-基础
查看>>
APC注入
查看>>
No enclosing instance of type Hello is accessible
查看>>
windows SVN搭建
查看>>
Scrum立会报告+燃尽图(Beta阶段第二周第二次)
查看>>
动态代理
查看>>
WCF 中,出现The remote server returned an unexpected response: (400) Bad Request.
查看>>
缓存概要
查看>>
vue项目中使用百度地图的方法
查看>>
[Vue-rx] Stream an API using RxJS into a Vue.js Template
查看>>