博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
闭锁CountDownLatch和栅栏CyclicBarrier之异同举例
阅读量:6111 次
发布时间:2019-06-21

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

  hot3.png

CountDownLatch和CyclicBarrier的主要联系和区别如下:

1.闭锁CountDownLatch做减计数,而栅栏CyclicBarrier则是加计数。
2.CountDownLatch是一次性的,CyclicBarrier可以重用。
3.CountDownLatch强调一个线程等多个线程完成某件事情。CyclicBarrier是多个线程互等,等大家都完成。
4.鉴于上面的描述,CyclicBarrier在一些场景中可以替代CountDownLatch实现类似的功能。
另外,值得一提的是,CountDownLatch和CyclicBarrier在创建和启动线程时,都没有明确提到同时启动全部线程,事实上这在技术上是不大可能,不必要,不提倡的。
先看例子一:

class SubRunnable implements Runnable {    private CountDownLatch begin, end;    private List
 sublist;        public SubRunnable(List
 sublist, CountDownLatch begin,CountDownLatch end) {        this.sublist = sublist;                this.begin = begin;        this.end = end;    }        @Override    public void run() {        try {            begin.await();                                    if (sublist != null) {                for (int i : sublist) {                    System.out.println("线程" + Thread.currentThread().getName() + ", i = " + i);                }            }        } catch (InterruptedException e) {            e.printStackTrace();        } finally{            System.out.println(System.currentTimeMillis() + ",线程" + Thread.currentThread().getName() + ",开始执行!");            end.countDown();        }    }}public class BatchWithCountDownLatch {    private static final int MAX = 3;        private static void list(List
 list) {        if(list == null){            list = new ArrayList
();        }                for(int i = 0 ;i < 1000;i++){            list.add(i);        }    }    public static void main(String[] args) {        List
 list = new ArrayList
();        list(list);                //把list拆分成多个        int mod = list.size() % MAX;        int threadCount = mod == 0 ? list.size() / MAX : list.size() / MAX + 1;        ExecutorService executors = Executors.newFixedThreadPool(threadCount);                CountDownLatch begin = new CountDownLatch(1);         CountDownLatch end = new CountDownLatch(threadCount);                         for(int i = 0; i< threadCount;i++){            int subsize = (i + 1) * MAX;            executors.execute(new SubRunnable(list.subList(i * MAX, subsize > list.size() ? list.size() : subsize),begin,end));        }                System.out.println("开始 !");        begin.countDown();        long startTime = System.currentTimeMillis();                try {            end.await();        } catch (InterruptedException e) {            e.printStackTrace();        } finally {            System.out.println("线程" + Thread.currentThread().getName() + "," + System.currentTimeMillis() + ", 所有线程已完成,开始进入下一步!");            System.out.println("花费时间 -> " + (System.currentTimeMillis() - startTime) + " ms");        }                System.out.println("开始进入第二步操作! ");                        System.out.println("end! ");    }}

这是根据jdk文档中的伪代码例程,编写的一个例子,我们完全可以将这个例程改为只使用一个CountDownLatch来实现之。经过测试,发现begin的引入对程序基本无用,当list是1000的数量级时,最先启动的线程仍然比最后启动的快几十毫秒左右;而不设置begin开始闭锁的程序,也是完全一样的情况。

例子二:

class SubRunnable implements Runnable {    private CyclicBarrier cyclicBarrier;    private List
 sublist;        public SubRunnable(List
 sublist, CyclicBarrier cyclicBarrier) {        this.sublist = sublist;        this.cyclicBarrier = cyclicBarrier;    }        @Override    public void run() {                try {            System.out.println(System.currentTimeMillis() + ",线程" + Thread.currentThread().getName() + ",开始执行!");            if(sublist != null){                for(int i : sublist){                    System.out.println("线程" + Thread.currentThread().getName() + ", i = " + i);                }            }            cyclicBarrier.await();        } catch (InterruptedException | BrokenBarrierException e) {            e.printStackTrace();        }    }    }public class ReplaceCountDownLatch {    private static final int MAX = 3;        private static void list(List
 list) {        if(list == null){            list = new ArrayList
();        }                for(int i = 0 ;i < 10;i++){            list.add(i);        }    }        public static void main(String[] args) throws InterruptedException, BrokenBarrierException {        List
 list = new ArrayList
();        list(list);        //把list拆分成多个        int mod = list.size() % MAX;        int threadCount = mod == 0 ? list.size() / MAX : list.size() / MAX + 1;        ExecutorService executors = Executors.newFixedThreadPool(threadCount);        final CyclicBarrier cyclicBarrier = new CyclicBarrier(threadCount,new Runnable() {            @Override            public void run() {                //根据jdkdoc里的描述,哪个线程最后运行完,就执行下面的代码。                System.out.println("线程" + Thread.currentThread().getName() + "," + System.currentTimeMillis() + ", 所有线程已完成,开始进入下一步!");            }        });                for(int i = 0; i< threadCount;i++){            int subsize = (i + 1) * MAX;            executors.execute(new SubRunnable(list.subList(i * MAX, subsize > list.size() ? list.size() : subsize),cyclicBarrier));        }                cyclicBarrier.await();        executors.shutdown();        System.out.println("开始进入第二步操作! ");                        System.out.println("end! ");    }}

使用栅栏CyclicBarrier实现和上面闭锁CountDownLatch相同的功能。

转载于:https://my.oschina.net/ramboo/blog/421945

你可能感兴趣的文章
醋泡大蒜有什么功效
查看>>
hdu 5115(2014北京—dp)
查看>>
数据结构中常见的树(BST二叉搜索树、AVL平衡二叉树、RBT红黑树、B-树、B+树、B*树)...
查看>>
PHP读取日志里数据方法理解
查看>>
第五十七篇、AVAssetReader和AVAssetWrite 对视频进行编码
查看>>
Vivado增量式编译
查看>>
一个很好的幻灯片效果的jquery插件--kinMaxShow
查看>>
微信支付签名配置正确,但返回-1,调不出支付界面(有的手机能调起,有的不能)...
查看>>
第二周例行报告
查看>>
Spring学习(16)--- 基于Java类的配置Bean 之 基于泛型的自动装配(spring4新增)...
查看>>
实验八 sqlite数据库操作
查看>>
四种简单的排序算法(转)
查看>>
Quartz2D之着色器使用初步
查看>>
多线程条件
查看>>
Git [remote rejected] xxxx->xxxx <no such ref>修复了推送分支的错误
查看>>
Porter/Duff,图片加遮罩setColorFilter
查看>>
黄聪:VMware安装Ubuntu10.10【图解】转
查看>>
Centos 6.x 升级openssh版本
查看>>
公式推♂倒题
查看>>
vue实现点击展开,点击收起
查看>>