iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Java中CyclicBarrier和CountDownLatch的用法与区别
  • 411
分享到

Java中CyclicBarrier和CountDownLatch的用法与区别

2024-04-02 19:04:59 411人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

目录前言CountDownLatch例子CyclicBarrier构造函数例子两者区别前言 CyclicBarrier和CountDownLatch这两个工具都是在java.util

前言

CyclicBarrier和CountDownLatch这两个工具都是在java.util.concurrent包下,并且平时很多场景都会使用到。
本文将会对两者进行分析,记录他们的用法和区别。

CountDownLatch

CountDownLatch是一个非常实用的多线程控制工具类,称之为“倒计时器”,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行。

CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭上等待的线程就可以恢复执行任务。

在这里插入图片描述

特点

只能一次性使用(不能reset);主线程阻塞;某个线程中断将永远到不了屏障点,所有线程都会一直等待。

例子


 	//创建初始化3个线程的线程池
    private ExecutorService                    threadPool     = Executors.newFixedThreadPool(3);
    //保存每个学生的平均成绩
    private ConcurrentHashMap<String, Integer> map            = new ConcurrentHashMap<>();
    private CountDownLatch                     countDownLatch = new CountDownLatch(3);

    private void count() {
        for (int i = 0; i < 3; i++) {
            threadPool.execute(() -> {
                //计算每个学生的平均成绩,代码略()假设为60~100的随机数
                int score = (int) (Math.random() * 40 + 60);
                try {
                    Thread.sleep(Math.round(Math.random() * 1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                map.put(Thread.currentThread().getName(), score);
                System.out.println(Thread.currentThread().getName() + "同学的平均成绩为" + score);
                countDownLatch.countDown();
            });
        }
        this.run();
        threadPool.shutdown();
    }

    @Override
    public void run() {
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        int result = 0;
        Set<String> set = map.keySet();
        for (String s : set) {
            result += map.get(s);
        }
        System.out.println("三人平均成绩为:" + (result / 3) + "分");
    }

    public static void main(String[] args) throws InterruptedException {
        long now = System.currentTimeMillis();
        CyclicBarrier1 cb = new CyclicBarrier1();
        cb.count();
        Thread.sleep(100);
        long end = System.currentTimeMillis();
        System.out.println(end - now);
    }

最终输出结果:

在这里插入图片描述

其中1194ms证明了会阻塞主线程。

CyclicBarrier

CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。

这个屏障之所以用循环修饰,是因为在所有的线程释放彼此之后,这个屏障是可以重新使用的(reset()方法重置屏障点),这一点与CountDownLatch不同。

CyclicBarrier是一种同步机制允许一组线程相互等待,等到所有线程都到达一个屏障点才退出await方法,它没有直接实现AQS而是借助ReentrantLock来实现的同步机制。它是可循环使用的,而CountDownLatch是一次性的,另外它体现的语义也跟CountDownLatch不同,CountDownLatch减少计数到达条件采用的是release方式,而CyclicBarrier走向屏障点(await)采用的是Acquire方式,Acquire是会阻塞的,这也实现了CyclicBarrier的另外一个特点,只要有一个线程中断那么屏障点就被打破,所有线程都将被唤醒(CyclicBarrier自己负责这部分实现,不是由AQS调度的),这样也避免了因为一个线程中断引起永远不能到达屏障点而导致其他线程一直等待。屏障点被打破的CyclicBarrier将不可再使用(会抛出BrokenBarrierException)除非执行reset操作。

构造函数

CyclicBarrier有两个构造函数:

CyclicBarrier(int parties)
int类型的参数表示有几个线程来参与这个屏障拦截,(拿上面的例子,即有几个人跟团旅游);

CyclicBarrier(int parties,Runnable barrierAction)
当所有线程到达一个屏障点时,优先执行barrierAction这个线程。

最重要的一个方法:
await();每个线程调用await(),表示我已经到达屏障点,然后当前线程被阻塞。

例子


	//创建初始化3个线程的线程池
    private ExecutorService                    threadPool     = Executors.newFixedThreadPool(3);
    //创建3个CyclicBarrier对象,执行完后执行当前类的run方法
    private CyclicBarrier                      cb             = new CyclicBarrier(3, this);
    //保存每个学生的平均成绩
    private ConcurrentHashMap<String, Integer> map            = new ConcurrentHashMap<>();

    private void count() {
        for (int i = 0; i < 3; i++) {
            threadPool.execute(() -> {
                //计算每个学生的平均成绩,代码略()假设为60~100的随机数
                int score = (int) (Math.random() * 40 + 60);
                try {
                    Thread.sleep(Math.round(Math.random() * 1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                map.put(Thread.currentThread().getName(), score);
                System.out.println(Thread.currentThread().getName() + "同学的平均成绩为" + score);
                try {
                    //执行完运行await(),等待所有学生平均成绩都计算完毕
                    cb.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
            });
        }
        threadPool.shutdown();
    }

    @Override
    public void run() {
        int result = 0;
        Set<String> set = map.keySet();
        for (String s : set) {
            result += map.get(s);
        }
        System.out.println("三人平均成绩为:" + (result / 3) + "分");
    }

    public static void main(String[] args) throws InterruptedException {
        long now = System.currentTimeMillis();
        CyclicBarrier1 cb = new CyclicBarrier1();
        cb.count();
        Thread.sleep(100);
        long end = System.currentTimeMillis();
        System.out.println(end - now);
    }

最终输出结果:

在这里插入图片描述

显然没有阻塞主线程。

两者区别

  • CountDownLatch的计数器只能使用一次。而CyclicBarrier的计数器可以使用reset()
  • 方法重置。所以CyclicBarrier能处理更为复杂的业务场景,比如如果计算发生错误,可以重置计数器,并让线程们重新执行一次。
  • CyclicBarrier还提供其他有用的方法,比如getNumberWaiting方法可以获得CyclicBarrier阻塞的线程数量。isBroken方法用来知道阻塞的线程是否被中断。比如以下代码执行完之后会返回true。
  • CountDownLatch会阻塞主线程,CyclicBarrier不会阻塞主线程,只会阻塞子线程。
  • 某线程中断CyclicBarrier会抛出异常,避免了所有线程无限等待。

我们来从jdk作者设计的目的来看,javadoc是这么描述它们的:

CountDownLatch:
A synchronization aid that allows one or more threads to wait until a set of operations being perfORMed in other threads completes.

CyclicBarrier:
A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.

从javadoc的描述可以得出:

CountDownLatch:一个或者多个线程,等待其他多个线程完成某件事情之后才能执行;
CyclicBarrier:多个线程互相等待,直到到达同一个同步点,再继续一起执行。
对于CountDownLatch来说,重点是“一个线程(多个线程)等待”,而其他的N个线程在完成“某件事情”之后,可以终止,也可以等待。而对于CyclicBarrier,重点是多个线程,在任意一个线程没有完成,所有的线程都必须等待。

CountDownLatch是计数器,线程完成一个记录一个,只不过计数不是递增而是递减,而CyclicBarrier更像是一个阀门,需要所有线程都到达,阀门才能打开,然后继续执行。

到此这篇关于Java中CyclicBarrier和CountDownLatch的用法与区别的文章就介绍到这了,更多相关Java CyclicBarrier CountDownLatch内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Java中CyclicBarrier和CountDownLatch的用法与区别

本文链接: https://www.lsjlt.com/news/133242.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java中CyclicBarrier和CountDownLatch的用法与区别
    目录前言CountDownLatch例子CyclicBarrier构造函数例子两者区别前言 CyclicBarrier和CountDownLatch这两个工具都是在java.util...
    99+
    2022-11-12
  • 解析阿里一面CyclicBarrier和CountDownLatch的区别
    引言 前面一篇文章我们《Java线程并发工具类CountDownLatch原理及用法》它有一个缺点,就是它的计数器只能够使用一次,也就是说当计数器(state)减到为 0的时候,如果...
    99+
    2022-11-11
  • java多线程中的并发工具类CountDownLatch,CyclicBarrier和Semaphore该怎么理解
    本篇文章给大家分享的是有关java多线程中的并发工具类CountDownLatch,CyclicBarrier和Semaphore该怎么理解,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起...
    99+
    2023-06-22
  • java中类与方法的区别
    什么是类?类是对象的模子,具有相同属性和方法的一组对象的集合,类是不存在的,是用来描述对象信息。在计算机的世界里面,计算机关注的事数据信息,我们描述数据信息的时候一定要要描述数据类型,对象就是具体的数据信息,类是信息的数据类型。什么是方法?...
    99+
    2014-06-01
    java基础 java 方法 区别
  • Java中BIO、NIO和AIO的区别、原理与用法
    目录IOBIONIOAIO区别及联系各自适用场景使用方式IO 什么是IO? 它是指计算机与外部世界或者一个程序与计算机的其余部分的之间的接口。它对于任何计算机系统都非常关键,...
    99+
    2022-11-12
  • Java Ribbon与openfeign区别和用法讲解
    目录Ribbon 本地负载均衡器本地负载均衡与Nginx 的区别基本使用原理分析openfeign基本使用Ribbon 本地负载均衡器 在SpringCloud第一代中使用Ribbo...
    99+
    2022-11-13
    Java Ribbon Java openfeign
  • java中“/”与“%”的区别
    区别:%是求模运算符,/是除运算符。%是求余运算,/是普通的除号。实例:System.out.println(3/5) = 0; System.out.println(2/5) = 0; System.out.println(4/5) ...
    99+
    2020-06-30
    java入门 java / % 区别
  • java中方法引用与方法调用的区别
    方法引用:方法引用返回的是接口的实现 。 private static Iterable itToIterable(Stream stream) { return stream::iterator; //编译通过此处返回...
    99+
    2018-03-02
    java基础 java 方法引用 方法调用 区别
  • select_related和prefetch_related的用法与区别
    0. 本文借助django-debug-toolbar来展现效果 (19条消息) django-debug-toolbar的安装_骑台风走的博客-CSDN博客https://blog.csdn.net/qq_52385631/article...
    99+
    2023-09-02
    数据库 sql mysql
  • java中equals与“==”的区别
    区别:== 比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否是指相同一个对象。比较的是真正意义上的指针操作。equals用来比较的是两个对象的内容是否相等,由于所有的类都是继承自java.lang....
    99+
    2017-05-07
    java equals == 区别
  • React中State与Props区别和用法
    本篇内容介绍了“React中State与Props区别和用法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!...
    99+
    2022-10-19
  • java中类方法与对象方法的区别
    类方法和对象方法的区别如下:对象方法必须用对象调用,类方法必须用类来调用对象方法中可以直接访问属性(成员变量),类方法中不可以直接访问属性(成员变量)类方法和对象方法可以进行相互调用1对象方法中可以直接调用类方法2类方法中间接调用对象方法 ...
    99+
    2021-04-22
    java入门 java 类方法 对象方法 区别
  • java中类方法与实例方法的区别
    一、类方法类方法是静态方法,前面需要有static修饰符修饰。类方法内不能涉及有关变量的内容。不能调用类的对象方法不能引用对象变量类方法不能被重写(覆盖)类方法不能使用super, this关键字二、实例方法可以调用类的对象方法可以引用对象...
    99+
    2020-02-10
    java基础 java 类方法 实例方法 区别
  • java中volatile和synchronized的区别与联系
    java中volatile和synchronized的区别与联系这个可能是最好的对比volatile和synchronized作用的文章了。volatile是一个变量修饰符,而synchronized是一个方法或块的修饰符。所以我们使用这两...
    99+
    2023-05-31
    volatile synchronized ava
  • Java中方法重写与重载的区别
    目录一、重写(Override)二、重载(Overload)三、总结Java方法重写(Override)与重载(Overload)的区别(超详细) 首页在我们要学习这个知识点之前,应...
    99+
    2022-11-13
  • vue中LocalStorage与SessionStorage的区别与用法
    目录什么是LocalStorage什么是SessionStorageLocalStorage与SessionStorage的区别LocalStorage与SessionStorage...
    99+
    2022-11-12
  • java中i++与++i的区别
    i++是先赋值,再运算,++i是先运算,再赋值。实例如下:package com.test; public class TestAdd { public static void main(String[] args) { ...
    99+
    2017-03-13
    java入门 java i++ ++i 区别
  • java中int与integer的区别
    一、java基本数据类型及其封装类java数据类型有基本数据类型和引用数据类型,为了方便将基本数据类型当作对象处理,java引入了基本数据类型相对应的封装类,如int封装类是Integer。在线教学视频分享:java教学视频二、java自动...
    99+
    2020-09-16
    java入门 java int integer 区别
  • java中long与Long的区别
    java中long与Long的区别是:long是java中的基本数据类型,而Long是java中对象类型;对于Long类型的数据,该数据是一个对象,而对于long类型的数据,该数据是一个基本数据类型,不属于对象。Java的数据类型分为两种:...
    99+
    2021-12-04
    java基础 java long Long 区别
  • java中double与float的区别
    java中double与float的区别:(推荐:java视频教程)单精度浮点数(float)与双精度浮点数(double)的区别如下:(1)在内存中占有的字节数不同单精度浮点数在机内占4个字节双精度浮点数在机内占8个字节(2)有效数字位数...
    99+
    2015-06-15
    java
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作