美文网首页
CountDownLatch 和 CyclicBarrier

CountDownLatch 和 CyclicBarrier

作者: 骊骅 | 来源:发表于2017-07-19 11:50 被阅读23次

    what?

    • CountDownLatch是什么


    • CyclicBarrier是什么?

    感性认识CountDownLatch

    以工人和老板关系为例,老板等待所有工人干完活才开始检查
    CountDownLatch示例代码

    • worker代码
    package concurrency.in.practice.countdownlatchtest;
    
    import java.util.Random;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.TimeUnit;
    
    /**
     * Created by haicheng.lhc on 19/07/2017.
     *
     * @author haicheng.lhc
     * @date 2017/07/19
     */
    public class Worker implements Runnable {
    
        private CountDownLatch downLatch;
        private String name;
    
        public Worker(CountDownLatch downLatch, String name) {
            this.downLatch = downLatch;
            this.name = name;
        }
    
        public void run() {
            this.doWork();
            try {
                TimeUnit.SECONDS.sleep(new Random().nextInt(10));
            } catch (InterruptedException ie) {
            }
            System.out.println(this.name + "活干完了!");
            this.downLatch.countDown();
    
        }
    
        private void doWork() {
            System.out.println(this.name + "正在干活!");
        }
    }
    
    
    • Boss代码
    package concurrency.in.practice.countdownlatchtest;
    
    import java.util.concurrent.CountDownLatch;
    
    /**
     * Created by haicheng.lhc on 19/07/2017.
     *
     * @author haicheng.lhc
     * @date 2017/07/19
     */
    public class Boss implements Runnable {
    
        private CountDownLatch downLatch;
    
        public Boss(CountDownLatch downLatch) {
            this.downLatch = downLatch;
        }
    
        public void run() {
            System.out.println("老板正在等所有的工人干完活......");
            try {
                this.downLatch.await();
            } catch (InterruptedException e) {
            }
            System.out.println("工人活都干完了,老板开始检查了!");
        }
    }
    
    • CountDownLatchDemo代码
    
    package concurrency.in.practice.countdownlatchtest;
    
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    /**
     * Created by haicheng.lhc on 19/07/2017.
     *
     * @author haicheng.lhc
     * @date 2017/07/19
     */
    public class CountDownLatchDemo {
    
        public static void main(String[] args) {
            ExecutorService executor = Executors.newCachedThreadPool();
    
            CountDownLatch latch = new CountDownLatch(3);
    
            Worker w1 = new Worker(latch,"张三");
            Worker w2 = new Worker(latch,"李四");
            Worker w3 = new Worker(latch,"王二");
    
            Boss boss = new Boss(latch);
    
            executor.execute(w3);
            executor.execute(w2);
            executor.execute(w1);
            executor.execute(boss);
    
            executor.shutdown();
        }
    }
    
    
    • 运行结果

    CountDownLatch 使用场景

    • 实现最大的并行性:有时我们想同时启动多个线程,实现最大程度的并行性。例如,我们想测试一个单例类。如果我们创建一个初始计数为1的CountDownLatch,并让所有线程都在这个锁上等待,那么我们可以很轻松地完成测试。我们只需调用 一次countDown()方法就可以让所有的等待线程同时恢复执行。
    • 开始执行前等待n个线程完成各自任务:例如应用程序启动类要确保在处理用户请求前,所有N个外部系统已经启动和运行了。
    • 死锁检测:一个非常方便的使用场景是,你可以使用n个线程访问共享资源,在每次测试阶段的线程数目是不同的,并尝试产生死锁。

    感性认识CyclicBarrier

    以所有室友都到齐了,每个人才可以点菜为例

    • Roommate代码
    
    package concurrency.in.practice.cyclicbarriertest;
    
    import java.util.concurrent.BrokenBarrierException;
    import java.util.concurrent.CyclicBarrier;
    
    /**
     * Created by haicheng.lhc on 19/07/2017.
     *
     * @author haicheng.lhc
     * @date 2017/07/19
     */
    public class Roommate implements Runnable {
    
        private CyclicBarrier barrier;
        private static int Count = 1;
        private int id;
    
        public Roommate(CyclicBarrier barrier) {
            this.barrier = barrier;
            this.id = Count++;
        }
    
    
        @Override
        public void run() {
    
            System.out.println(id + " : 我到了");
            try {
                //通知barrier,已经完成动作,在等待
                barrier.await();
                System.out.println("Id " + id + " : 点菜吧!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
    
    
        }
    }
    
    
    • CyclicBarrierDemo代码
    
    package concurrency.in.practice.cyclicbarriertest;
    
    import java.util.concurrent.CyclicBarrier;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    /**
     * Created by haicheng.lhc on 19/07/2017.
     *
     * @author haicheng.lhc
     * @date 2017/07/19
     */
    public class CyclicBarrierDemo {
    
        public static void main(String[] args) {
            CyclicBarrier barrier = new CyclicBarrier(5, new Runnable() {
                //栅栏动作,在计数器为0的时候执行
                @Override
                public void run() {
                    System.out.println("我们都准备好了.");
                }
            });
    
            ExecutorService es = Executors.newCachedThreadPool();
            for (int i = 0; i < 5; i++) {
                es.execute(new Roommate(barrier));
            }
    
        }
    }
    
    
    • 测试结果

    CyclicBarrier使用场景

    CyclicBarrier可以用于多线程计算数据,最后合并计算结果的应用场景。比如我们用一个Excel保存了用户所有银行流水,每个Sheet保存一个帐户近一年的每笔银行流水,现在需要统计用户的日均银行流水,先用多线程处理每个sheet里的银行流水,都执行完之后,得到每个sheet的日均银行流水,最后,再用barrierAction用这些线程的计算结果,计算出整个Excel的日均银行流水。

    相关文章

      网友评论

          本文标题:CountDownLatch 和 CyclicBarrier

          本文链接:https://www.haomeiwen.com/subject/pyclkxtx.html