• CountDownLatch与CyclicBarrier的使用与区别


    CountDownLatch的介绍和使用:

    一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。

    用给定的计数 初始化 CountDownLatch。由于调用了 countDown() 方法,所以在当前计数到达0之前,await 方法会一直受阻塞。

    之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。如果需要重置计数,请考虑使用 CyclicBarrier。

    使用场景:

    在一些应用场合中,需要等待某个条件达到要求后才能做后面的事情;同时当线程都完成后也会触发事件,以便进行后面的操作。

    这个时候就可以使用CountDownLatch。CountDownLatch最重要的方法是countDown()和await(),前者主要是倒数一次,后者是等待倒数到0,如果没有到达0,就只有阻塞等待了。

    相关实例

    // 一个CountDouwnLatch实例是不能重复使用的,也就是说它是一次性的,锁一经被打开就不能再关闭使用了,如果想重复使用,请考虑使用CyclicBarrier。
    public class CountDownLatchTest {
        // 模拟了100米赛跑,10名选手已经准备就绪,只等裁判一声令下。当所有人都到达终点时,比赛结束。
        public static void main(String[] args) throws InterruptedException {
            // 开始的倒数锁 
            final CountDownLatch begin = new CountDownLatch(1);  
            // 结束的倒数锁 
            final CountDownLatch end = new CountDownLatch(10);  
            // 十名选手 
            final ExecutorService exec = Executors.newFixedThreadPool(10);  
            for (int index = 0; index < 10; index++) {
                final int NO = index + 1;  
                Runnable run = new Runnable() {
                    public void run() {  
                        try {  
                            // 如果当前计数为零,则此方法立即返回。
                            // 等待
                            begin.await();  
                            Thread.sleep((long) (Math.random() * 10000));  
                            System.out.println("No." + NO + " arrived");  
                        } catch (InterruptedException e) {  
                        } finally {  
                            // 每个选手到达终点时,end就减一
                            end.countDown();
                        }  
                    }  
                };  
                exec.submit(run);
            }  
            System.out.println("Game Start");  
            // begin减一,开始游戏
            begin.countDown();  
            // 等待end变为0,即所有选手到达终点
            end.await();  
            System.out.println("Game Over");  
            exec.shutdown();  
        }
    }

    以上实例转自:http://www.itzhai.com/the-introduction-and-use-of-a-countdownlatch.html

    CyclicBarrier和CountDownLatch一样,都是关于线程的计数器。

    用法略有不同,测试代码如下:

    public class TestCyclicBarrier {
        private static final int THREAD_NUM = 5;    
        public static class WorkerThread implements Runnable{
            CyclicBarrier barrier;
            public WorkerThread(CyclicBarrier b){
                this.barrier = b;
            }
            public void run() {
                try{
                    System.out.println("Worker's waiting");
                    //线程在这里等待,直到所有线程都到达barrier。
                    barrier.await();
                    System.out.println("ID:"+Thread.currentThread().getId()+" Working");
                }catch(Exception e){
                    e.printStackTrace();
                }
            }
        }
        public static void main(String[] args) {
            CyclicBarrier cb = new CyclicBarrier(THREAD_NUM, new Runnable() {
                //当所有线程到达barrier时执行public void run() {
                    System.out.println("Inside Barrier");
                }
            });
            for(int i=0;i<THREAD_NUM;i++){
                new Thread(new WorkerThread(cb)).start();
            }
        }
    
    }
    /*
    以下是输出:
    Worker's waiting
    Worker's waiting
    Worker's waiting
    Worker's waiting
    Worker's waiting
    Inside Barrier
    ID:12 Working
    ID:8 Working
    ID:11 Working
    ID:9 Working
    ID:10 Working
    */
    1.  CyclicBarrier初始化时规定一个数目,然后计算调用了CyclicBarrier.await()进入等待的线程数。当线程数达到了这个数目时,所有进入等待状态的线程被唤醒并继续。 
    2.  CyclicBarrier就象它名字的意思一样,可看成是个障碍, 所有的线程必须到齐后才能一起通过这个障碍。 
    3.  CyclicBarrier初始时还可带一个Runnable的参数, 此Runnable任务在CyclicBarrier的数目达到后,所有其它线程被唤醒前被执行

    两者区别

    http://xumingming.sinaapp.com/215/countdownlatch-vs-cyclicbarrier/

  • 相关阅读:
    Kubernates集群搭建
    Spring Security——基于表达式的权限控制
    JVM常用命令参数
    Spring 注解原理
    Linux SSH免登陆配置步骤
    错误日志收集sentry的安装与简单使用
    java.lang.UnsupportedClassVersionError
    docker maven 出错:Failed to execute goal com.spotify:docker-maven-plugin:...: Request error: POST https://192.168.99.100:2376/build?t=
    redis哨兵配置主从
    spring-data-redis使用哨兵配置一主多从
  • 原文地址:https://www.cnblogs.com/pingh/p/3506493.html
Copyright © 2020-2023  润新知