zoukankan      html  css  js  c++  java
  • CountDownLatch和CyclicBarrier区别

    CountDownLatch : 一个线程(或者多个), 等待另外N个线程完成某个事情之后才能执行。 
    CyclicBarrier : N个线程相互等待,任何一个线程完成之前,所有的线程都必须等待。 

    倒计时器:CountDownLatch

    CountDownLatch是一个非常实用的多线程控制工具类。常用的就下面几个方法:

    CountDownLatch(int count) //实例化一个倒计数器,count指定计数个数
    countDown() // 计数减一
    await() //等待,当计数减到0时,所有线程并行执行
    

    CountDownLatch在我工作的多个场景被使用,算是用的很频繁的了,比如我们的API接口响应时间被要求在200ms以内,但是如果一个接口内部依赖多个三方/外部服务,那串行调用接口的RT必然很久,所以个人用的最多的是接口RT优化场景,内部服务并行调用。

    对于倒计数器,一种典型的场景就是火箭发射。在火箭发射前,为了保证万无一失,往往还要进行各项设备、仪器的检测。只有等到所有的检查完毕后,引擎才能点火。那么在检测环节当然是多个检测项可以同时进行的。代码实现:

    /**
     * @Author: 王琦 <QQ.Eamil>1124602935@qq.com</QQ.Eamil>
     * @Date: 2019-5-4 0004 9:43
     * @Description: 倒计时器示例:火箭发射
     */
    public class CountDownLatchDemo implements Runnable{
    
        static final CountDownLatch latch = new CountDownLatch(10);
        static final CountDownLatchDemo demo = new CountDownLatchDemo();
    
        @Override
        public void run() {
            // 模拟检查任务
            try {
                Thread.sleep(new Random().nextInt(10) * 1000);
                System.out.println("check complete");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                //计数减一
                //放在finally避免任务执行过程出现异常,导致countDown()不能被执行
                latch.countDown();
            }
        }
    
    
        public static void main(String[] args) throws InterruptedException {
            ExecutorService exec = Executors.newFixedThreadPool(10);
            for (int i=0; i<10; i++){
                exec.submit(demo);
            }
    
            // 等待检查
            latch.await();
    
            // 发射火箭
            System.out.println("Fire!");
            // 关闭线程池
            exec.shutdown();
        }
    }
    

    上述代码中我们先生成了一个CountDownLatch实例。计数数量为10,这表示需要有10个线程来完成任务,等待在CountDownLatch上的线程才能继续执行。latch.countDown();方法作用是通知CountDownLatch有一个线程已经准备完毕,倒计数器可以减一了。latch.await()方法要求主线程等待所有10个检查任务全部准备好才一起并行执行。

    CyclicBarrier例子:
    public class CyclicBarrierTest {
    private final static int THREAD_NUM = 10;
    public static void main(String[] args) {
    CyclicBarrier lock = new CyclicBarrier(THREAD_NUM, new Runnable() {
    @Override public void run() {
    System.out.println("大家都准备完成了00000000");
    }
    });
    ExecutorService exec = Executors.newCachedThreadPool();
    for (int i = 0; i < THREAD_NUM; i++) {
    exec.submit(new CountdownLatchTask(lock, "Thread-"+i));
    }
    exec.shutdown();
    }

    static class CountdownLatchTask implements Runnable{
    private final CyclicBarrier lock;
    private final String threadName;
    CountdownLatchTask(CyclicBarrier lock, String threadName) {
    this.lock = lock;
    this.threadName = threadName;
    }
    @Override public void run() {
    // for (int i = 0; i < 3; i++) {
    System.out.println(threadName + " 准备完成");
    try {
    lock.await();
    } catch (BrokenBarrierException e) {
    e.printStackTrace();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(threadName + " 执行完成111111111");
    // }
    }
    }
    }
  • 相关阅读:
    多媒体基础知识之PCM数据
    FFmpeg在Linux下编译使用
    AndroidStudio 中使用FFMPEG
    Android 音频播放分析笔记
    【Linux 命令】- more和less
    【Linux】- 简明Vim练习攻略
    【Linux】- 对find,xargs,grep和管道的一些理解
    【Linux 命令】- find 命令
    【Linux 命令】- tar 命令
    【Linux】- CentOS7 下 安装 supervisor
  • 原文地址:https://www.cnblogs.com/lvgg/p/11535144.html
Copyright © 2011-2022 走看看