zoukankan      html  css  js  c++  java
  • CountDownLatch和CycliBarrier介绍

    一、CountDownLatch

      它被用来同步一个或多个任务,强制他们等待其他任务完成,这就是闭锁。

    public CountDownLatch(int count) {
            if (count < 0) throw new IllegalArgumentException("count < 0");
            this.sync = new Sync(count);
        }

      类中只有一个构造函数,一个int类型的参数count,代表计数器。这个计数器的初始值是线程的数量,每当一个线程结束,count-1,当count==0 时,所有线程执行完毕,在闭锁上等待的线程就可以执行了。

    类中还包含了三个公共方法:

    public void await()
    public boolean await(long timeout, TimeUnit unit)
    public void countDown()

      当每个任务完成时,都会调用countDown()方法。而等待问题被解决的任务在这个锁存器上调用await()方法,这个任务就相当于被挂起了直到 timeout 或 计数器为0

    public class CountDownLatchDemo {
        static final int SIZE = 5;
    
        public static void main(String[] args) {
            ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 10, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(5));
            CountDownLatch countDownLatch = new CountDownLatch(SIZE);
            pool.execute(new WaitTask(countDownLatch));
            for (int i = 0; i < SIZE; i++) {
                pool.execute(new TaskNow(countDownLatch));
            }
        }
    
    }
    
    class TaskNow implements Runnable {
        private final CountDownLatch countDownLatch;
    
        TaskNow(CountDownLatch countDownLatch) {
            this.countDownLatch = countDownLatch;
        }
    
        @Override
        public void run() {
            try {
                TimeUnit.MILLISECONDS.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("我没完事你别想跑");
            //调用countDown()的方法会减少count次数直到为0,调用await的任务才能进行
            countDownLatch.countDown();
        }
    }
    
    class WaitTask implements Runnable {
        private final CountDownLatch countDownLatch;
    
        WaitTask(CountDownLatch countDownLatch) {
            this.countDownLatch = countDownLatch;
        }
    
        @Override
        public void run() {
            try {
                //调用await的任务会被挂起
                countDownLatch.await();
                System.out.println("终于轮到我了");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    结果:

      我没完事你别想跑
      我没完事你别想跑
      我没完事你别想跑
      我没完事你别想跑
      我没完事你别想跑
      终于轮到我了

    二、CylicBarrier

      栅栏类似于闭锁,只是要等到所有线程都到达栅栏,才能进行接下来的动作,在没到达栅栏之前先到的要等待。

    构造方法

    共有两个构造方法:

    public CyclicBarrier(int parties, Runnable barrierAction) {
            if (parties <= 0) throw new IllegalArgumentException();
            this.parties = parties;
            this.count = parties;
            this.barrierCommand = barrierAction;
        }
    public CyclicBarrier(int parties) {
            this(parties, null);
        }

    CyclicBarrier默认的构造方法是CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每个线程使用await()方法告诉CyclicBarrier我已经到达了屏障,然后当前线程被阻塞。

    CyclicBarrier的另一个构造函数CyclicBarrier(int parties, Runnable barrierAction),用于线程到达屏障时,优先执行barrierAction,方便处理更复杂的业务场景。

    await()方法

      线程调用await()方法表示已经到达同步点,然后当前线程被阻塞。直到parties个参与线程调用了await()方法,CyclicBarrier同样提供带超时时间的await和不带超时时间的await方法:

    public int await() throws InterruptedException, BrokenBarrierException {
        try {
            return dowait(false, 0L);
        } catch (TimeoutException toe) {
            throw new Error(toe); // cannot happen
        }
    }
    public int await(long timeout, TimeUnit unit)throws InterruptedException,BrokenBarrierException,TimeoutException{...}

      可以看到await方法调用了dowait()方法,dowait()方法是核心方法其内容是:如果这个线程不是最后一个到达的线程那么进行等待直到:

    • 最后一个线程到达,即index == 0
    • 某个参与线程等待超时
    • 某个参与线程被中断
    • 调用了CyclicBarrier的reset()方法。该方法会将屏障重置为初始状态

    案例

    public class CycliBarrierDemo {
    
    
        public static void main(String[] args) {
            int threadCount = 3;
            CyclicBarrier cyclicBarrier = new CyclicBarrier(threadCount);
            ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 10, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1));
            for (int i = 0; i < threadCount; i++) {
                pool.execute(new Horse(cyclicBarrier, i));
            }
        }
    }
    
    class Horse implements Runnable {
        private CyclicBarrier cyclicBarrier;
        private int num;
    
        public Horse(CyclicBarrier cyclicBarrier, int num) {
            this.cyclicBarrier = cyclicBarrier;
            this.num = num;
        }
    
        @Override
        public void run() {
            System.out.println("马匹:" + num + "到了");
            try {
                cyclicBarrier.await();
                System.out.println("马匹:" + num + "在等待");
                TimeUnit.MILLISECONDS.sleep(2000);
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
            System.out.println("马匹到齐");
        }
    }


    结果:

      马匹:0到了
      马匹:2到了
      马匹:1到了
      马匹:1在等待
      马匹:0在等待
      马匹:2在等待
      马匹到齐
      马匹到齐
      马匹到齐

     

      

  • 相关阅读:
    Linux Centos7之由Python2升级到Python3教程
    10张图带你深入理解Docker容器和镜像
    Centos7 添加用户及设置权限
    OpenCV 和 Dlib 人脸识别基础
    python unittest 源码学习
    Markdown 模板
    python Django ORM相关
    java的介绍
    java反射
    代理模式
  • 原文地址:https://www.cnblogs.com/xcgShare/p/11765231.html
Copyright © 2011-2022 走看看