CountDownLatch、CyclicBarrier 的对比

Stella981
• 阅读 791

CountDownLatch、CyclicBarrier 都可以用于: 在多线程异步执行过程中,执行预定的流程后唤醒 指定的线程 进行相应的操作.
区别:
1,CountDownLatch 唤醒过一次,就废弃了;CyclicBarrier可以重复之前的预定流程,反复唤醒。
2,CountDownLatch 可用于唤醒主线程,异步线程[任意线程,只要有他的实例];CyclicBarrier只能用于唤醒异步线程[貌似]。
3,CountDownLatch 唤醒指定线程后,当前线程并不阻塞;CyclicBarrier 唤醒指定线程后,当前线程会阻塞,等指定线程执行完成后,当前线程才继续执行。
应用场景:
CountDownLatch:异步转同步,,,
CyclicBarrier:批量多线程汇总,像短时间跑批类的,
总结:
CyclicBarrier我是用的比较少,大部分场景都是用CountDownLatch就可以了。

package test;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;

/**
 * CountDownLatch、CyclicBarrier 都可以用于: 在多线程异步执行过程中,执行预定的流程后唤醒 指定的线程 进行相应的操作.<br>
 *
 * 区别:<br>
 * 1,CountDownLatch 唤醒过一次,就废弃了;CyclicBarrier可以重复之前的预定流程,反复唤醒。<br>
 * 2,CountDownLatch 可用于唤醒主线程,异步线程[任意线程,只要有他的实例];CyclicBarrier只能用于唤醒异步线程[貌似]。<br>
 * 3,CountDownLatch 唤醒指定线程后,当前线程并不阻塞;CyclicBarrier唤醒指定线程后,当前线程会阻塞,等指定线程执行完成后,当前线程才继续执行。<br>
 * 
 * 应用场景:<br>
 * CountDownLatch:异步转同步,,,<br>
 * CyclicBarrier:批量多线程汇总,像短时间跑批类的,<br>
 * 
 * 总结:<br>
 * CyclicBarrier我是用的比较少,大部分场景都是用CountDownLatch就可以了。
 * 
 * @author Yuanqy
 *
 */
public class TestLatch {

    @org.junit.Test
    public void test() throws InterruptedException {
        // ==CountDownLatch===================================
        try {
            final CountDownLatch latch = new CountDownLatch(5);
            long i = latch.getCount();
            for (int j = 0; j < i; j++) {
                new Thread() {
                    @Override
                    public void run() {
                        System.out.println("CountDownLatch:" + latch.getCount() + "\t" + this.getName());//线程存在并发
                        latch.countDown();// 计数递减,当==0时 唤醒等待线程。
                    }
                }.start();// 异步执行
            }
            latch.await();// 阻塞,直到latch.getCount()==0时唤醒
            System.out.println("===Main1 is finish===");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // ==CyclicBarrier===================================
        final CyclicBarrier cb = new CyclicBarrier(5, new Thread() {
            @Override
            public void run() {
                System.out.println("===Last is finish===");//到达指定次数唤醒
            }
        });
        for (int i = 0; i < cb.getParties(); i++) {
            new Thread("Thread_" + i) {
                @Override
                public void run() {
                    try {
                        for (int x = 0; x < 2; x++) {// 我是可以重复使用的哦。
                            // cb.getNumberWaiting()返回已被await()的线程数量,不能用于计数。
                            Thread.sleep(500);
                            System.out.println("CyclicBarrier:" + cb.getNumberWaiting() + "\t" + this.getName());
                            cb.await();// 阻塞当前线程, 唤醒CyclicBarrier 预定的线程先执行,当前线程等待
                            System.out.println("Please watch me!\t" + this.getName());
                        }
                    } catch (InterruptedException | BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }
            }.start();// 异步执行
        }
        System.out.println("===Main2 is finish===");//这里不阻塞
        Thread.currentThread().join();
    }
}

测试结果:

CountDownLatch:5    Thread-0
CountDownLatch:5    Thread-1
CountDownLatch:3    Thread-2
CountDownLatch:2    Thread-3
CountDownLatch:1    Thread-4
===Main1 is finish===
===Main2 is finish===
CyclicBarrier:0    Thread_2
CyclicBarrier:0    Thread_0
CyclicBarrier:0    Thread_1
CyclicBarrier:3    Thread_3
CyclicBarrier:4    Thread_4
===Last is finish===
Please watch me!    Thread_4
Please watch me!    Thread_0
Please watch me!    Thread_1
Please watch me!    Thread_2
Please watch me!    Thread_3
CyclicBarrier:0    Thread_0
CyclicBarrier:0    Thread_1
CyclicBarrier:0    Thread_4
CyclicBarrier:3    Thread_2
CyclicBarrier:4    Thread_3
===Last is finish===
Please watch me!    Thread_3
Please watch me!    Thread_2
Please watch me!    Thread_4
Please watch me!    Thread_1
Please watch me!    Thread_0
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
腾讯java社招面试流程,附大厂真题面经
拼多多一面首先自我介绍参加过哪些项目并发编程三要素?实现可见性的方法有哪些?多线程的价值?创建线程的三种方式的对比?画出线程的状态流转图常用的并发工具类有哪些?CyclicBarrier和CountDownLatch的区别CAS的问题:1、CAS容易造成ABA问题2、不能保证代码块的原子性3、CAS造成CPU利用率增加ReadWriteL
Wesley13 Wesley13
3年前
4、jstack查看线程栈信息
1、介绍利用jps、top、jstack命令找到进程中耗时最大的线程,以及线程状态等等,同时最后还可以显示出死锁的线程查找:FoundoneJavaleveldeadlock即可1、jps获得进程号!(https://oscimg.oschina.net/oscnet/da00a309fa6
Stella981 Stella981
3年前
CountDownLatch和CylicBarrier以及Semaphare你使用过吗
CountDownLatch是什么CountDownLatch的字面意思:倒计时门栓它的功能是:让一些线程阻塞直到另一些线程完成一系列操作后才唤醒。它通过调用await方法让线程进入阻塞状态等待倒计时0时唤醒。它通过线程调用countDown方法让倒计时中的计数器减去1,当计数器为0时,会唤醒哪些因为调用了await而阻塞的线程。
Wesley13 Wesley13
3年前
Java CyclicBarrier介绍
CyclicBarrier(周期障碍)类可以帮助同步,它允许一组线程等待整个线程组到达公共屏障点。CyclicBarrier是使用整型变量构造的,其确定组中的线程数。当一个线程到达屏障时(通过调用CyclicBarrier.await()),它会被阻塞,直到所有线程都到达屏障,然后在该点允许所有线程继续执行。与CountDownLatch不同的
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这