JUC工具类_CyclicBarrier与CountDownLatch

news2024/10/6 8:27:50

最近被问到CyclicBarrier和CountDownLatch相关的面试题,CountDownLatch平时工作中经常用到,但是CyclicBarrier没有用过,一时答不上来,因此简单总结记录一下

1.什么是CyclicBarrier?

1.1 概念

CyclicBarrier(循环屏障)是Java中的一个同步辅助类,它允许一组线程相互等待,直到达到某个公共屏障点。它的工作方式是,在所有参与线程都到达屏障之前,它们会一直等待。一旦最后一个线程到达屏障,所有被屏障等待的线程将被释放,可以继续执行后续的任务。

1.2 原理

CyclicBarrier内部维护了一个计数器,用于追踪到达屏障点的线程数量。当线程调用了CyclicBarrier的await()方法时,它会被阻塞,直到达到指定的等待数量。当最后一个线程调用await()方法时,屏障将打开,所有被阻塞的线程都会被释放,并且屏障会被重置以便下一次使用。

下面来看一下CyclicBarrier 主要属性

// ReentrantLock 重入锁
private final ReentrantLock lock = new ReentrantLock();
// 条件锁,等达到一定数量了再唤醒
private final Condition trip = lock.newCondition();
// 需要等待的线程数量
private final int parties;
// 当唤醒的时候执行的命令
private final Runnable barrierCommand;
// 代
private Generation generation = new Generation();
// 当前这一代还需要等待的线程数
private int count;

CyclicBarrier 存在如下构造方法,parties表示需要等待的线程数
在这里插入图片描述

CyclicBarrier 中await()方法表示等待线程,await()方法的实现逻辑来自dowait()方法
image-20231118010254634

好比如CyclicBarrier内部维护了一个计数器

image-20231118010352841

1.3 使用案例

CyclicBarrier可以用于解决需要多个线程协同工作的场景,例如将一个任务分成多个子任务并行执行,然后等待所有子任务完成后再继续执行后续操作。它也可以用于模拟多个线程相互等待的场景,直到所有线程都准备就绪,然后一起开始执行。

/**
 * <p>Class: TaskParallelExecution</p>
 * <p>Description: 使用CyclicBarrier演示多任务同时执行</p>
 *
 * @author zhouyi
 * @version 1.0
 * @date 2023/11/18
 */
public class TaskParallelExecution {
    private static final int NUM_THREADS = 4;

    public static void main(String[] args) {
        CyclicBarrier barrier = new CyclicBarrier(NUM_THREADS, () -> {
            System.out.println("All tasks completed. Proceeding to next step.");
        });

        for (int i = 0; i < NUM_THREADS; i++) {
            int threadNum = i;
            Thread t = new Thread(() -> {
                System.out.println("Task " + threadNum + " started.");
                // 模拟任务的执行
                try {
                    Thread.sleep(2000); // 假设任务需要2秒完成
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Task " + threadNum + " completed.");
                try {
                    barrier.await(); // 等待其他线程完成任务
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
                System.out.println("Task " + threadNum + " continues with the next step.");
            });
            t.start();
        }
    }
}

image-20231118011338132

在实际开发中,常见的还有如下几个业务场景,比如:

  • 数据处理并行化:在大规模数据处理中,可以将数据分成多个部分,每个部分由一个线程处理。使用CyclicBarrier,每个线程在处理完自己的数据后等待其他线程完成,然后进行下一步的数据合并或汇总操作。
  • 并行计算任务:在并行计算中,可以将一个大任务分解成多个子任务,并行处理。每个子任务处理一部分数据,然后等待其他子任务完成,最后合并结果。CyclicBarrier可用于同步各个子任务的执行。
  • 多线程任务协同:在某些场景下,多个线程需要协同工作,例如多个线程同时从不同的地方获取数据,然后合并处理这些数据。CyclicBarrier可用于等待所有线程都准备就绪后,再同时开始数据获取和处理的过程。

这些是一些使用CyclicBarrier的实际生产中的常见案例。CyclicBarrier提供了一种方便的同步机制,使多个线程能够协同工作,等待彼此达到一个共同的屏障点,然后再继续执行后续操作。

2.什么是CountDownLatch?

2.1 概念

CountDownLatch是Java中的一个同步辅助类,它允许一个或多个线程等待其他线程完成操作后再继续执行。它的工作方式与CyclicBarrier相反:它通过一个计数器来实现等待,计数器初始化为一个正整数,每个线程完成操作后会将计数器减1,直到计数器变为0,等待的线程才会被释放。

2.2 原理

CountDownLatch包含两个主要方法:

  • countDown():每当一个线程完成了所需的操作,调用该方法将计数器减1。
  • await():调用该方法的线程会阻塞,直到计数器变为0,即所有线程都完成了操作。

CountDownLatch通常用于一个线程等待其他若干个线程完成某个操作后再继续执行。例如,主线程希望等待多个子线程完成初始化操作后再开始执行某个任务,可以使用CountDownLatch来实现。

2.3 使用案例

使用CountDownLatch实现倒计时功能,例如模拟三个线程,当三个线程都一起执行结束后再统一交给主线程处理。

public class CountDownLatchExample {
    private static final int NUM_THREADS = 3;

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(NUM_THREADS);

        for (int i = 0; i < NUM_THREADS; i++) {
            Thread t = new Thread(() -> {
                // 模拟每个线程的操作
                System.out.println("Thread " + Thread.currentThread().getId() + " started.");
                try {
                    Thread.sleep(2000); // 假设每个线程需要2秒完成操作
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread " + Thread.currentThread().getId() + " completed.");
                latch.countDown(); // 操作完成后将计数器减1
            });
            t.start();
        }

        System.out.println("Main thread is waiting for other threads to complete.");
        latch.await(); // 主线程等待计数器变为0
        System.out.println("All threads have completed. Proceeding with the main thread.");
    }
}

以上案例执行结果如下

image-20231118012905177

除了以上案例外,实际开发中经常遇到类似的场景,例如采用多线程处理大数据量导入,我们可以通过多线程分批读取数据、校验、封装数据,当以上几个环节都成功后(CountDownLatch 减少为0时)就可以进行写库操作,可以认为没有数据缺失。

3.总结

CyclicBarrier和CountDownLatch是Java中的两个同步辅助类,它们有一些共同点,但也存在一些区别。

共同点:

  1. 两者都是用于线程间的同步和协作,可以控制线程的执行顺序和并发性。
  2. 都使用一个计数器来控制等待和释放线程的操作。
  3. 都可以用于解决多线程之间的协同工作问题。

区别:

  1. 计数器行为不同:
    • CyclicBarrier的计数器可以重用,当计数器减到0时,所有等待的线程会被释放,计数器会被重置为初始值,可以继续使用。
    • CountDownLatch的计数器只能减少一次,一旦减到0,所有等待的线程会被释放,计数器不能重置或再次使用。
  2. 等待操作方式不同:
    • CyclicBarrier使用await()方法进行等待,当线程调用await()时,它会阻塞直到所有线程都到达屏障点,然后一起继续执行。
    • CountDownLatch使用await()方法进行等待,当线程调用await()时,它会阻塞直到计数器变为0,然后线程被释放。
  3. 使用场景不同:
    • CyclicBarrier通常用于将一个大任务分解为多个子任务并行执行,然后等待所有子任务完成后再继续执行后续操作。它适用于多线程协同工作的场景。
    • CountDownLatch通常用于一个或多个线程等待其他线程完成操作后再继续执行。它适用于线程之间的等待和同步的场景。

数器变为0,然后线程被释放。
3. 使用场景不同:

  • CyclicBarrier通常用于将一个大任务分解为多个子任务并行执行,然后等待所有子任务完成后再继续执行后续操作。它适用于多线程协同工作的场景。
  • CountDownLatch通常用于一个或多个线程等待其他线程完成操作后再继续执行。它适用于线程之间的等待和同步的场景。

CyclicBarrier和CountDownLatch都是用于线程间的同步和协作,但它们的计数器行为、等待操作方式和使用场景有所不同。CyclicBarrier适用于任务分解和并行执行的场景,而CountDownLatch适用于线程之间的等待和同步的场景。在选择使用时,需要根据具体需求来确定使用哪个类更合适。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1221753.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

php中RESTful API使用

1、RESTful AP是什么 RESTful API是一种软件架构风格 RESTful API基于HTTP协议&#xff0c;并遵循一系列约定和原则。它的设计理念是将资源&#xff08;Resource&#xff09;作为核心概念&#xff0c;并通过一组统一的接口对资源进行操作。API的资源通常通过URL进行标识&…

Linux grep 命令

Linux grep 命令 1&#xff1a; 作用 ​ grep是一种文本搜索工具&#xff0c;它能使用特定的搜索模式&#xff0c;包括[正则表达式]搜索文本&#xff0c;并默认输出匹配行。 ​ windows类似的命令是findstr. 2&#xff1a;语法 grep -options&#xff08;参数&#xff09;…

Spring Boot - devtools 热部署

spring-boot-devtools是Spring Boot提供的一组开发工具&#xff0c;它旨在提高开发体验。这些工具包括应用程序的自动重新启动、自动刷新和远程调试等功能。下面是将spring-boot-devtools整合到Spring Boot应用程序中的步骤&#xff1a; 0、启用"Build project automatic…

【AI视野·今日Sound 声学论文速览 第三十六期】Mon, 30 Oct 2023

AI视野今日CS.Sound 声学论文速览 Mon, 30 Oct 2023 Totally 7 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Sound Papers Style Description based Text-to-Speech with Conditional Prosodic Layer Normalization based Diffusion GAN Authors Neeraj Kumar, A…

开发知识点-前端-webpack

webpack技术笔记 一、 介绍二、 下载使用 一、 介绍 Webpack是一个现代 JavaScript 应用程序的静态模块打包器 打包&#xff1a;可以把js、css等资源按模块的方式进行处理然后再统一打包输出 静态&#xff1a;最终产出的静态资源都可以直接部署到静态资源服务器上进行使用 模…

达尔优EK87键盘说明书

EK87说明书连接说明&#xff1a; **有线模式&#xff1a;**开关拨到最右边&#xff0c;然后插线连接电脑即可使用 2.4G **接收器模式&#xff1a;**开关拨到中间&#xff0c;然后接收器插入电脑USB接口即可使用 **蓝牙模式&#xff1a;**开关拨到最左边&#xff0c;然后按FNQ长…

<Linux>(极简关键、省时省力)《Linux操作系统原理分析之Linux 进程管理 2》(6)

《Linux操作系统原理分析之Linux 进程管理 2》&#xff08;6&#xff09; 4 Linux 进程管理4.2 Linux 进程的状态和标识4.2.1 Linux 进程的状态及转换4.2.2 Linux 进程的标识4.2.3 进程标识哈希表 4 Linux 进程管理 4.2 Linux 进程的状态和标识 4.2.1 Linux 进程的状态及转换…

Navicat 基于 GaussDB 主备版的快速入门

Navicat Premium&#xff08;16.2.8 Windows版或以上&#xff09; 已支持对GaussDB 主备版的管理和开发功能。它不仅具备轻松、便捷的可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结构同步、协同合作、数据迁移等&#xff09;&#xff0c;这…

API接口怎么对接电商平台获取商品详情数据

对于api接口的对接&#xff0c;你可以按照以下步骤进行操作&#xff1a; 1. 确定需求&#xff1a;首先要明确你的对接需求&#xff0c;即想要通过对接api接口实现什么功能&#xff0c;例如获取数据、实现支付等。 2. 寻找文档&#xff1a;在对接之前&#xff0c;要找到相关ap…

一、认识STM32

目录 一、初识STM32 1.1 STM32的命名规则介绍 1.2 STM32F103ZET6资源配置介绍 二、如何识别芯片管脚 2.1 如何寻找 IO 的功能说明 三、构成最小系统的要素 一、初识STM32 1.1 STM32的命名规则介绍 以 STM32F103ZET6 来讲解下 STM32 的命名方法&#xff1a; &…

AH4056线性锂电池充电IC:高效、安全的充电解决方案

随着移动设备的普及&#xff0c;人们对电池续航能力的要求越来越高。为了满足这一需求&#xff0c;电池充电技术不断创新。本文将为您介绍一款AH4056线性锂电池充电IC&#xff0c;采用同步整流技术&#xff0c;具有宽输入电压范围、大充电电流、温度保护等优点&#xff0c;适用…

虾皮产品标题生成器:为您的商品打造吸引眼球的标题

在电商平台上&#xff0c;一个引人注目的商品标题是吸引潜在买家点击进入您的产品页面的第一步。然而&#xff0c;很多商家在创建商品标题时遇到困难&#xff0c;不知道如何吸引更多的目标受众。幸运的是&#xff0c;现在有一个名为知虾工具的强大工具&#xff0c;可以帮助商家…

【Git学习二】时光回溯:git reset和git checkout命令详解

&#x1f601; 作者简介&#xff1a;一名大四的学生&#xff0c;致力学习前端开发技术 ⭐️个人主页&#xff1a;夜宵饽饽的主页 ❔ 系列专栏&#xff1a;JavaScript小贴士Git等软件工具技术的使用 &#x1f450;学习格言&#xff1a;成功不是终点&#xff0c;失败也并非末日&a…

基于STM32的无线传感器网络(WSN)通信方案设计与实现

无线传感器网络&#xff08;Wireless Sensor Network&#xff0c;简称WSN&#xff09;是由一组分布式的无线传感器节点组成的网络&#xff0c;用于监测和收集环境中的各类物理信息。本文将基于STM32微控制器&#xff0c;设计并实现一个简单的无线传感器网络通信方案&#xff0c…

系统韧性研究(5)| 常用的系统韧性技术

如果不利事件或条件导致系统无法正常运行&#xff0c;则它们可能会对有价值的资产造成各种形式的损害。正如我在本系列的前几篇文章中概述的那样&#xff0c;系统韧性很重要&#xff0c;因为没有人想要一个无法克服“不可避免的逆境”的脆弱系统。 在本系列的第一篇文章中&…

nacos客户端连接服务端报Client not connected, current status:STARTING

说明&#xff1a; nacos服务端版本&#xff1a;v2.1.2 nacos客户端版本&#xff1a;2.1.2 结果启动项目报错&#xff1a; Client not connected, current status:STARTING 解决&#xff1a; 降低客户端版本至 1.4.1 就Ok了 <dependency><groupId>com.alibaba.naco…

AI监管规则:各国为科技监管开辟了不同的道路

AI监管规则&#xff1a;各国为科技监管开辟了不同的道路 一份关于中国、欧盟和美国如何控制AI的指南。 编译 李升伟 茅 矛 &#xff08;特趣生物科技有限公司&#xff0c;广东深圳&#xff09; 插图&#xff1a;《自然》尼克斯宾塞 今年5月&#xff0c;科技公司OpenAI首席…

List is a raw type. References to generic type List<E> should be parameterized

List is a raw type. References to generic type List<E> should be parameterized 都是代码习惯问题懒

syncthing 多设备同步

【精选】linux间文件实时同步(syncthing) ---带历史版本“后悔药”_syncthing linux_井底蛙-jdw的博客-CSDN博客https://blog.csdn.net/qq_41355314/article/details/116694273 wget https://gh-proxy.com/https://github.com/syncthing/syncthing/releases/download/v1.26.1/…

基于R语言平台Biomod2模型的物种分布建模与可视化分析

!](https://img-blog.csdnimg.cn/84e1cc8c7f9b4b6ab60903ffa17d82f0.jpeg#pic_center)