专栏名称: 庄杰森
目录
相关文章推荐
中国证券报  ·  房贷利率,下调 ·  昨天  
中国证券报  ·  超9000亿,A股最重要增量资金! ·  2 天前  
华泰睿思  ·  华泰研究年度特辑——海外视野篇 ·  3 天前  
上海证券报  ·  一日三事故!波音回应 ·  4 天前  
51好读  ›  专栏  ›  庄杰森

CountDownLatch与CyclicBarrier区别(源码实现)

庄杰森  · 掘金  ·  · 2018-01-29 02:44

正文

测试代码



/**
 * CountDownLatch
 * CyclicBarrier 区别
 *
 * 网上说 CyclicBarrier 与 CountDownLatch 区别只是一个能重置一个不行
 * 其实看过源码不止区别在此
 *
 * 调用
 * countDownLatch.countDown();
 * 线程会直接执行完,计数器减1
 *
 * countDownLatch.await(); 只会阻塞当前线程
 *
 * 而
 * 调用
 * cyclicBarrier.await();
 * 线程会阻塞,直到最后一个线程也调用 await(); 时,才能全部释放
 * 这时候会有个 惊群 的问题出现
 *
 * 所以
 * 使用 countDownLatch 会比较好
 *
 * Created by zhuangjiesen on 2018/1/24.
 */
public class CountDownLatchAndBarrierTest {


    public static void main(String[] args) {
        //保活
        Thread t4 = new Thread(new Runnable() {
            @Override
            public void run() {

                while(true) {
                    ThreadHelper.sleep(300);
                }
            }
        });
        t4.start();

//        testCountDownLatch();
        testCyclicBarrier();
    }


    public static void testCountDownLatch(){

        final CountDownLatch countDownLatch = new CountDownLatch(4);

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(" t1 start ....");
                countDownLatch.countDown();
                System.out.println(" t1 await over ....");
                ThreadHelper.sleep(300);
            }
        });


        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(" t2 start ....");
                countDownLatch.countDown();
                System.out.println(" t2 await over ....");
                ThreadHelper.sleep(300);
            }
        });
        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(" t3 start ....");
                countDownLatch.countDown();
                System.out.println(" t3 await over ....");
                ThreadHelper.sleep(300);
            }
        });
        t1.start();
        t2.start();
        t3.start();
    }


    public static void testCyclicBarrier(){

        final CyclicBarrier cyclicBarrier = new CyclicBarrier(4);
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(" t1 start ....");
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
                System.out.println(" t1 await over ....");
                ThreadHelper.sleep(300);
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(" t2 start ....");
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
                System.out.println(" t2 await over ....");
                ThreadHelper.sleep(300);
            }
        });
        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(" t3 start ....");
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
                System.out.println(" t3 await over ....");
                ThreadHelper.sleep(300);
            }
        });

        t1.start();
        t2.start();
        t3.start();
    }


}


运行结果:

testCyclicBarrier();

 t1 start ....
 t3 start ....
 t2 start ....

testCountDownLatch();

 t1 start ....
 t3 start ....
 t2 start ....
 t3 await over ....
 t1 await over ....
 t2 await over ....

结论:


CyclicBarrier 源码是通过 lock / condition 
signal 和 await 的, 所以它实现的效果是阻塞当前线程

CountDownLatch 源码是设计一个 继承 aqs 的内部类,
设置 state 的值
当 countDown(); 时,是去 releaseShared(); 释放锁,
然后当state 等于 0 时,就唤醒await(); 等待的线程;
所以 CountDownLatch.countDown(); 时,线程是直接继续执行的,所以也不用进行异常处理

推荐文章
中国证券报  ·  房贷利率,下调
昨天
中国证券报  ·  超9000亿,A股最重要增量资金!
2 天前
华泰睿思  ·  华泰研究年度特辑——海外视野篇
3 天前
上海证券报  ·  一日三事故!波音回应
4 天前
深夜发媸  ·  身上哪些小物件会让你显 low ?
7 年前
新媒体课堂  ·  看完这30句话,新媒体人都自杀了
7 年前
Cisco思科CCIE俱乐部  ·  思维导图学网络之静态路由
7 年前