java 多线程编程 CountDownLatch(线程计数器) 和 CyclicBarrier 的用法

news2024/12/23 10:38:32

CountDownLatch - 线程计数器

包名:java.util.concurrent

功能:

多线程编程中,要并发请求10个接口,等这些接口都返回结果再进行统一处理后,将结果返回。

调用countDown() 方法 ,计数减去 1。

代码示例

调用countDown()方法后,会执行下面的源码

 

//此处需要maven 引入 commons-lang3 包
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.scheduling.annotation.Async;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
public class LockTest {

final CountDownLatch cdl = new CountDownLatch(10);

   @Test
    void testLatch() throws InterruptedException {
        //定义固定线程池
        ExecutorService exec = Executors.newFixedThreadPool(10);
        List<String> list = new ArrayList<>();
        //统计执行时间
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        for (int i = 0; i < 10; i++) {
            exec.execute(new Runnable() {
                @Override
                public void run() {
                    int sleep = RandomUtils.nextInt(1,10);
                    try {
                        System.out.println("当前线程:" + Thread.currentThread().getName() + ",休眠:" + sleep);
                        //此处模拟请求外部接口
                        TimeUnit.SECONDS.sleep(sleep);
                        //此处模拟返回结果
                        list.add(Thread.currentThread().getName() + "-" + sleep);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    //执行完一次,从计数器中释放线程
                    cdl.countDown();
                }
            });
        }
        //等待所有线程执行完
        cdl.await();

        //统一处理结果
        for (String s : list) {
            System.out.println(s);
        }
        stopWatch.stop();
        System.out.println("总计耗时:" + stopWatch.getTime() + "ms");
    }
}

执行结果:

当前线程:pool-1-thread-8,休眠:1
当前线程:pool-1-thread-2,休眠:3
当前线程:pool-1-thread-9,休眠:9
当前线程:pool-1-thread-7,休眠:2
当前线程:pool-1-thread-4,休眠:8
当前线程:pool-1-thread-3,休眠:4
当前线程:pool-1-thread-1,休眠:5
当前线程:pool-1-thread-6,休眠:7
当前线程:pool-1-thread-10,休眠:4
当前线程:pool-1-thread-5,休眠:6
pool-1-thread-8-1
pool-1-thread-7-2
pool-1-thread-2-3
pool-1-thread-10-4
pool-1-thread-3-4
pool-1-thread-1-5
pool-1-thread-5-6
pool-1-thread-6-7
pool-1-thread-4-8
pool-1-thread-9-9
总计耗时:9010ms

CyclicBarrier - 等待至barrier状态再全部同时执行(回环栅栏)

包名:java.util.concurrent

功能:

一组线程,等待他们各自执行完操作并且都调用 await() 方法,再同时执行各自后续的任务。

代码示例:

//此处需要maven 引入 commons-lang3 包
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.scheduling.annotation.Async;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
public class LockTest {

    CyclicBarrier barrier = new CyclicBarrier(5);

    @Test
    void testBarrier() throws InterruptedException {
        for (int i = 0; i < 5; i++) {
            //启动5个线程
            new Tests(barrier).start();
        }
        Thread.sleep(5000);
        System.out.println("继续操作");
    }

    static class Tests extends Thread {
        CyclicBarrier cyclicBarrier;
        Tests(CyclicBarrier barrier) {
            cyclicBarrier = barrier;
        }

        @Override
        public void run() {
            //模拟执行代码时长
            int r = RandomUtils.nextInt(1,5);
            System.out.println(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss") + "线程休眠:" + Thread.currentThread().getName() + ": " + r + "s");
            try {
                TimeUnit.SECONDS.sleep(r);
                //调用await()方法,线程处于barrier,等待所有线程都调用await()方法
                cyclicBarrier.await();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } catch (BrokenBarrierException e) {
                throw new RuntimeException(e);
            }
            //所有线程都调用await()方法后,执行后续的代码
            System.out.println(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss") + " 所有执行完成,继续向下执行: " + Thread.currentThread().getName());
        }

    }
}

执行结果:

2023-08-31 12:32:46线程休眠:Thread-2: 3s
2023-08-31 12:32:46线程休眠:Thread-4: 4s
2023-08-31 12:32:46线程休眠:Thread-3: 1s
2023-08-31 12:32:46线程休眠:Thread-1: 3s
2023-08-31 12:32:46线程休眠:Thread-5: 1s
2023-08-31 12:32:50 所有执行完成,继续向下执行: Thread-4
2023-08-31 12:32:50 所有执行完成,继续向下执行: Thread-1
2023-08-31 12:32:50 所有执行完成,继续向下执行: Thread-5
2023-08-31 12:32:50 所有执行完成,继续向下执行: Thread-3
2023-08-31 12:32:50 所有执行完成,继续向下执行: Thread-2
继续操作

结论

相同点:


CountDownLatch 和 CyclicBarrier 都能够实现线程之间的等待


区别


CountDownLatch 一般用于某个线程A等待若干个其他线程执行完任务之后,它才执行
CyclicBarrier 一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行
CountDownLatch 是不能够重用的,而 CyclicBarrier 是可以重用的。

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

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

相关文章

深度学习(前馈神经网络)知识点总结

用于个人知识点回顾&#xff0c;非详细教程 1.梯度下降 前向传播 特征输入—>线性函数—>激活函数—>输出 反向传播 根据损失函数反向传播&#xff0c;计算梯度更新参数 2.激活函数(activate function) 什么是激活函数&#xff1f; 在神经网络前向传播中&#x…

【Linux系列】离线安装openjdk17的rpm包

首发博客地址 首发博客地址[1] 系列文章地址[2] 视频地址[3] 准备 RPM 包 请从官网下载&#xff1a;https://www.oracle.com/java/technologies/downloads/#java17[4] 如需不限速下载&#xff0c;请关注【程序员朱永胜】并回复 1020 获取。 安装 yum localinstall jdk-17_linux…

renren-fast-vue环境升级后,运行正常打包后,访问页面空白

网上各种环境&#xff0c;路径都找了一遍&#xff0c;也没成功。后来发现升级后打包的dist文件结构发生了变化&#xff0c; 1.最开始正常版本是这样 2.升级后是这样&#xff0c;少了日期文件夹 3.问题&#xff1a;打包后的index.html中引入的是config文件夹&#xff0c;而打…

Matlab(画图进阶)

目录 大纲 1.特殊的Plots 1.1 loglog(双对数刻度图) ​1.3 plotyy(创建具有两个y轴的图形) 1.4yyaxis(创建具有两个y轴的图) 1.5 bar 3D条形图(bar3) 1.6 pie(饼图) 3D饼图 1.7 polar 2.Stairs And Ste阶梯图 3.Boxplot 箱型图和Error Bar误差条形图 3.1 boxplot 3.2 …

国外地址如何地理编码?Python三行代码解决!

对于单个地址基于Python中的geocoder库获取经纬度非常方便&#xff0c;代码如下&#xff1a; # codingutf-8 import geocoder # 输入地址 address Akala Temple lonLat geocoder.osm(address) print(lonLat.latlng) # 输出结果 [27.8569644, 84.0893767]若地址数量较多&am…

Gradio项目所学

从项目中学习Gradio&#xff1a;快速搭建AI算法可视化部署演示(侧重项目搭建与案例分享) 我们通常使用的两款AI可视化交互应用&#xff1a; Gradio 与 StreamList 本次我们通过项目案例对Gradio从简单使用到进阶进行讲解介绍 Gradio的优势 Gradio的优势在于其代码结构的简单性与…

Java“牵手”京东商品详情数据,京东API接口申请指南

京东平台商品详情接口是开放平台提供的一种API接口&#xff0c;通过调用API接口&#xff0c;开发者可以获取京东商品的标题、价格、库存、月销量、总销量、库存、详情描述、图片等详细信息 。 获取商品详情接口API是一种用于获取电商平台上商品详情数据的接口&#xff0c;通过…

面试总结 - 计算机网络

计算机网络 1 OSI 七层模型 | TCP与UDP | 响应状态码 OSI 模型 应用层: 计算机用户&#xff0c;以及各种应用程序和网络之间的接口&#xff0c;其功能是直接向用户提供服务&#xff0c;完成用户希望在网络上完成的各种工作。 HTTP SMTP FTP DNS 表示层: 负责数据格式的转换&…

鸿蒙系列-如何更好地使用 ArkUI 的 Image 组件?

如何使用好 ArkUI 的 Image 组件&#xff1f; 开发者经常需要在应用中显示一些图片&#xff0c;例如&#xff1a;按钮中的logo、网络图片、本地图片等。在应用中显示图片需要使用 Image 组件实现&#xff0c;Image支持多种图片格式&#xff0c;包括png、jpg、bmp、svg和gif&am…

实现公网远程访问:Windows本地快速搭建SFTP文件服务器并配置端口映射

文章目录 1. 搭建SFTP服务器1.1 下载 freesshd服务器软件1.3 启动SFTP服务1.4 添加用户1.5 保存所有配置 2 安装SFTP客户端FileZilla测试2.1 配置一个本地SFTP站点2.2 内网连接测试成功 3 使用cpolar内网穿透3.1 创建SFTP隧道3.2 查看在线隧道列表 4. 使用SFTP客户端&#xff0…

镜头翻转大师:视频剪辑高手的魔法技巧

在数字媒体时代&#xff0c;视频制作已成为各种规模的组织和个人的必备技能。无论是小型家庭活动还是大型企业项目&#xff0c;都需要通过视频来展示成果、传播信息&#xff0c;或是仅仅为了分享生活的美好瞬间。然而&#xff0c;视频制作并非易事&#xff0c;其中最困难的步骤…

气传导蓝牙耳机排行榜,值得大家选择的气传导耳机推荐!

​随着科技的不断进步&#xff0c;气传导耳机已经成为了市场上备受瞩目的产品之一。相比传统耳机&#xff0c;气传导耳机的音质表现更加出色&#xff0c;同时还具有更好的佩戴感受。下面跟着我脚步来&#xff0c;推荐几款值得大家选择的气传导耳机&#xff0c;看看哪款更好&…

【错误记录】exe4j 打包程序无法设置 jar 包依赖的问题 ( 将源码 和 依赖库打包到同一个 jar 包中 )

文章目录 一、问题描述二、解决方案 一、问题描述 在 【错误记录】IntelliJ IDEA 导出可执行 jar 包执行报错 ( java.lang.ClassNotFoundException | 打包时没有选择依赖库 ) 博客中遇到 java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriverat j…

[LeetCode周赛复盘] 第 360 场周赛20230827

[LeetCode周赛复盘] 第 360 场周赛20230827 一、本周周赛总结2833. 距离原点最远的点1. 题目描述2. 思路分析3. 代码实现 2834. 找出美丽数组的最小和2. 思路分析3. 代码实现 2835. 使子序列的和等于目标的最少操作次数1. 题目描述2. 思路分析3. 代码实现 2836. 在传球游戏中最…

Leetcode328 奇偶链表

思路&#xff1a;分别处理奇偶&#xff0c;保存奇偶的第一个和最后一个节点&#xff0c;注意最后链接的时候需要把偶数的next去掉再拼接不然就成环了 class Solution:def oddEvenList(self, head: ListNode) -> ListNode:if not head or not head.next or not head.next.ne…

数据结构与算法-递归回溯分治

引入思考&#xff1a; 1.微信分销系统中有一个返利&#xff0c;大家应该都知道&#xff0c;比如B是A的下线&#xff0c;C是B的下线&#xff0c;那么在分钱返利的时候A可以分B&#xff0c;C的钱&#xff0c;这时候我们是不是就要分别找B,C的最后上级。这个问题我们一般怎么来解决…

数据通信——传输层TCP(可靠传输机制的滑动窗口)

引言 之前提到过拥塞问题&#xff0c;如果大量数据疯狂涌入&#xff0c;接收端无法及时处理就会导致数据丢包&#xff0c;从而使得通信受到干扰。之前的连续ARQ如果不加以节制&#xff0c;疯狂发送报文&#xff0c;接收端无法及时返回ACK就会导致网络瘫痪。 滑动窗口机制协议 这…

Linux服务器部署JavaWeb后端项目

适用于&#xff1a;MVVM前后台分离开发、部署、域名配置 前端&#xff1a;Vue 后端&#xff1a;Spring Boot 这篇文章只讲后端部署&#xff0c;前端部署戳这里 目录 Step1&#xff1a;服务器上搭建后端所需环境1、更新服务器软件包2、安装JDK83、安装MySQL4、登录MySQL5、修…

一百六十六、MySQL——systemctl stop mysqld无法停止MySQL8.0服务

一、目的 为了解决MySQL的中文乱码问题&#xff0c;需要对/etc/my.cnf文件进行参数配置。 而对/etc/my.cnf文件进行配置参数之前&#xff0c;需要先停止MySQL服务 二、错误命令语句示范 &#xff08;一&#xff09;错误的命令语句 # systemctl stop mysqld &#xff08;…

SQL分组后取topN

准备数据 create table SC( SId varchar(10) comment "学生ID", CId varchar(10) comment "课程ID", score decimal(18,1) comment "课程成绩");insert into SC values(01 , 01 , 80); insert into SC values(01 , 02 , 90); insert into SC va…