可循环障碍CyclicBarrier 一次性减法CountDownLatch

隐身守侯 提交于 2020-01-06 14:12:02

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

其实两者的用法异曲同工

先说说CyclicBarrier,看看初始化:

有两种初始化,其实很容易理解,第一个是说多少个parties需要执行(通过调用CyclicBarrier.await()来计算线程数量),执行完成后BarrierAction最后收尾执行,第二个就是说多少个线程需要执行(通过调用CyclicBarrier.await()来计算线程数量),执行完成后不需要收尾。

功能:有多少个线程执行完之后所有线程才能一起执行下一个。

特性:使用AQS和CAS确保线程安全,调用await()会进入condition queue,然后等所有线程执行完成后,也就是count增加到指定值,然后会调用signalAll()将条件队列中的移入到sync queue去执行。

 

 

再说说CountDownLatch,初始化:

声明一个数字,然后调用自己的await方法,等待其他线程通过调用countDown方法将此数字减到0,然后唤醒当前的线程。

功能:当前线程等待其他线程执行完之后再执行。

特性:使用CAS和AQS保证线程安全

 

区别

1.cyclicBarrier使用加法到一定数目后唤醒所有线程,countDownLatch使用减法到0时唤醒主线程。

2.cyclicBarrier可以循环使用,可以通过reset方法去重置,countDownLatch是一次性的执行完就结束。

3.cyclicBarrier是让一堆线程等待然后一起再执行。countDownLatch是一个线程等待其他线程结束完成。

 

样例:

countDownLatch:

往集合里加是个元素,加个第五个的时候提示一下。

public static void main(String[] args) {
    
    CountDownLatch countDownLatch = new CountDownLatch(1);
    ConcurrentLinkedQueue clq = new ConcurrentLinkedQueue();
    B b = new B(countDownLatch);
    new Thread(b).start();
    A a = new A(countDownLatch, clq);
    new Thread(a).start();
}
static class A implements Runnable {
    CountDownLatch cdl  ;
    ConcurrentLinkedQueue clq  ;

    public A(CountDownLatch countDownLatch,ConcurrentLinkedQueue clq) {
        this.cdl = countDownLatch;
        this.clq = clq;
    }
    @Override
    public void run() {


        for(int i=0;i<9;i++) {
         clq.add("1");
            try {
                Thread.sleep(1000);

            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("添加第" + i + "个");
            if (clq.size() == 5) {
                cdl.countDown();
            }
        }
    }
}
static class B implements Runnable {
    CountDownLatch cdl  ;
    public B(  CountDownLatch cdl ){
        this.cdl = cdl;
    }

    @Override
    public void run() {
        try {
            cdl.await();
            System.out.println("已经5个了");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

cyclicBarrier:

计算十名员工的工资,形成表格汇总,通知员工领工资,然后员工再领工资。

public static void main(String[] args) throws BrokenBarrierException, InterruptedException {
        ConcurrentHashMap concurrentHashMap = new ConcurrentHashMap<String, Integer>();
        AtomicInteger a = new AtomicInteger();

        CyclicBarrier cyclicBarrier = new CyclicBarrier(10, new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                int size = concurrentHashMap.entrySet().size();

                System.out.println("所有线程计算完成,共" + size + "名,结果如下:");
                Iterator iterator = concurrentHashMap.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String, Integer> en = (Map.Entry<String, Integer>) iterator.next();

                    System.out.println(en.getKey() + ":" + en.getValue());
                }


            }
        });
        ThreadLocal<Integer> ad = new ThreadLocal<Integer>();
        ExecutorService exSer = newCachedThreadPool();
        //  A aa = new A();
        ThreadLocal<A> aa = new ThreadLocal<A>();
        for (int i = 0; i < 9; i++) {
            exSer.submit(new Runnable() {
                @Override
                public void run() {
//                    ad.set(a.incrementAndGet());
                    aa.set(new A(a.incrementAndGet()));
                    concurrentHashMap.put("员工" + (aa.get().getA()), Math.random() * 10000);
                    System.out.println(Thread.currentThread().getName() + "计算完成员工" + (aa.get().getA()) + "的工资");
                    try {
                        cyclicBarrier.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                    System.out.println("通知员工" + aa.get().getA() + "领工资啦");

                    try {
                        //等待是为了让reset生效
                        Thread.currentThread().sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("睡醒");
                    try {
                        cyclicBarrier.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }

                    exSer.submit(new Remove("员工" + aa.get().getA(), concurrentHashMap));

                }
            });


        }

        cyclicBarrier.await();

        System.out.println("cyclicBarrier.isBroken()---" + cyclicBarrier.isBroken());
        cyclicBarrier.reset();
        System.out.println("cyclicBarrier.isBroken()---" + cyclicBarrier.isBroken());
        cyclicBarrier.await();
       // exSer.shutdown();
    }

    static class A {
        public A(int a) {
            this.a = a;
        }

        int a;

        public int getA() {
            return a;
        }

        public void setA(int a) {
            this.a = a;
        }
    }


    static class Remove implements Runnable {
        String name;
        ConcurrentHashMap con;

        public Remove(String name, ConcurrentHashMap con) {
            this.name = name;
            this.con = con;
        }

        @Override
        public void run() {
            con.remove(name);
            System.out.println(name + "领取了工资");
        }
    }

运行结果:
pool-1-thread-6计算完成员工6的工资
pool-1-thread-8计算完成员工3的工资
pool-1-thread-2计算完成员工9的工资
pool-1-thread-1计算完成员工1的工资
pool-1-thread-7计算完成员工4的工资
pool-1-thread-5计算完成员工5的工资
pool-1-thread-3计算完成员工8的工资
pool-1-thread-4计算完成员工7的工资
pool-1-thread-9计算完成员工2的工资
所有线程计算完成,共9名,结果如下:
员工4:2342.2147453667794
员工3:2067.969946452305
员工2:4868.520645427759
员工1:5147.003352118165
员工9:3955.4686122160765
员工8:2043.424792081039
员工7:7147.287327017816
员工6:1023.2789412425269
员工5:1437.6584893765355
通知员工2领工资啦
通知员工6领工资啦
通知员工1领工资啦
通知员工5领工资啦
通知员工9领工资啦
通知员工3领工资啦
cyclicBarrier.isBroken()---false
通知员工7领工资啦
通知员工8领工资啦
通知员工4领工资啦
cyclicBarrier.isBroken()---false
 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!