当前位置: 首页 > news >正文

Java多线程编程-栅栏CyclicBarrier实例

前言

本文是基于《Java多线程编程实战指南-核心篇》第五章个人理解,源码是摘抄作者的源码,源码会加上自己的理解。读书笔记目前笔者正在更新如下, 《Java多线程编程实战指南-核心篇》,《How Tomcat Works》,再到《spring 源码》解读。

栅栏CyclicBarrier


有时候多个线程可能需要相互等待对方执行到代码中某个地方(集合点),这这些线程才能继续执行。这种等待类似于大家相约去爬山的情形:大家实现约定好时间到集合点,先到的人必须在集合点等待其他未到的人,只有所有参与人员到齐之后大家才能够触发去登山。Java.util.concurrent.CyclicBarrier,该类就可以用来实现这种等待。

使用CyclicBarrier实现等待的线程被成为参与方,参与方只需要执行CyclicBarrier.await()就可以实现等待。尽管从应用代码的角度来看,参与方是并发执行CyclicBarrier.await()的,但是CyclicBarrier内部维护了一个显示锁,总是能区分出最后一个执行CyclicBarrier.await()的线程。除了最后一个线程外,任何参与方都被暂停,处于WAITING状态。最后一个线程执行await时候,会唤醒其他参与方,而最后一个线程自身不会暂停。

与CountDownLatch不同(有关CountDownLatch可以参考之前博客),在所有参与方唤醒时候,任何线程再次执行await又会暂停,直到这些线程最后一个线程执行了await

实例

实例模拟了士兵参与打靶训练,所有参与训练士兵被分为若干组Rank,每组被称为一排,一排士兵个数等于靶子的个数,每次只能够有一排士兵进行射击。一排士兵必须同时射击,射击完毕的士兵必须等待同排其他士兵射击完毕后才能整排撤离射击点。然后一排一排的轮流射击。

代码基本讲解

1.主函数ShootPractice实例化,输入参数为N(每排士兵个数=靶子个数),linecount(排数),lasting(最大持续时间),并且根据士兵数量(N*linecount)实例化了所有士兵存于rank中.

2.实例化了两个CycliBarrier,shiftBarrier和startBarrier,startBarrier保证同一时间士兵能在同一时间射击,可以理解为上图所示,士兵是否就绪,如图士兵一和四是站在射击地点了,处于就绪状态,需要等待士兵二和三。

而shiftBarrier,是确保所有士兵射击后同时撤离射击位置,这是由于有的士兵有的已经完成射击,有的还没有,如图士兵一和二已经射击结束,三和四还在射击,所以士兵一和二需要等待三和四。

3.所以在线程run函数的,在开火fire函数前后有两个等待,一个是等待所有人就绪,一个是等待所有人射击完成。

代码

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;public class ShootPractice {// 参与打靶训练的全部士兵final Soldier[][] rank;// 靶的个数,即每排中士兵的个数final int N;// 打靶持续时间(单位:秒)final int lasting;// 标识是否继续打靶volatile boolean done = false;// 用来指示进行下一轮打靶的是哪一排的士兵volatile int nextLine = 0;final CyclicBarrier shiftBarrier;final CyclicBarrier startBarrier;public ShootPractice(int N, final int lineCount, int lasting) {this.N = N;this.lasting = lasting;this.rank = new Soldier[lineCount][N];for (int i = 0; i < lineCount; i++) {for (int j = 0; j < N; j++) {rank[i][j] = new Soldier(i * N + j);}}shiftBarrier = new CyclicBarrier(N, new Runnable() {@Overridepublic void run() {// 更新下一轮打靶的排nextLine = (nextLine + 1) % lineCount;// 语句①Debug.info("Next turn is :%d", nextLine);}});// 语句②startBarrier = new CyclicBarrier(N);}public static void main(String[] args) throws InterruptedException {ShootPractice sp = new ShootPractice(4, 5, 24);sp.start();}public void start() throws InterruptedException {// 创建并启动工作者线程Thread[] threads = new Thread[N];for (int i = 0; i < N; ++i) {threads[i] = new Shooting(i);threads[i].start();}// 指定时间后停止打靶Thread.sleep(lasting * 1000);stop();for (Thread t : threads) {t.join();}Debug.info("Practice finished.");}public void stop() {done = true;}class Shooting extends Thread {final int index;public Shooting(int index) {this.index = index;}@Overridepublic void run() {Soldier soldier;try {while (!done) {soldier = rank[nextLine][index];// 一排中的士兵必须同时开始射击startBarrier.await();// 语句③// 该士兵开始射击soldier.fire();// 一排中的士兵必须等待该排中的所有其他士兵射击完毕才能够离开射击点shiftBarrier.await();// 语句④}} catch (InterruptedException e) {// 什么也不做} catch (BrokenBarrierException e) {e.printStackTrace();}}// run方法结束}// 类Shooting定义结束// 参与打靶训练的士兵static class Soldier {private final int seqNo;public Soldier(int seqNo) {this.seqNo = seqNo;}public void fire() {Debug.info(this + " start firing...");Tools.randomPause(5000);System.out.println(this + " fired.");}@Overridepublic String toString() {return "Soldier-" + seqNo;}}// 类Soldier定义结束
}

debug和tool可以参考之前博客

参考文献

《Java多线程编程实战-核心篇》

相关文章:

Java多线程编程-栅栏CyclicBarrier实例

前言 本文是基于《Java多线程编程实战指南-核心篇》第五章个人理解&#xff0c;源码是摘抄作者的源码&#xff0c;源码会加上自己的理解。读书笔记目前笔者正在更新如下&#xff0c; 《Java多线程编程实战指南-核心篇》&#xff0c;《How Tomcat Works》&#xff0c;再到《spr…...

【100天精通Python】Day67:Python可视化_Matplotlib 绘制动画,2D、3D 动画 示例+代码

1 绘制2D动画&#xff08;animation&#xff09; Matplotlib是一个Python绘图库&#xff0c;它提供了丰富的绘图功能&#xff0c;包括绘制动画。要绘制动画&#xff0c;Matplotlib提供了FuncAnimation类&#xff0c;允许您创建基于函数的动画。下面是一个详细的Matplotlib动画示…...

变量、常量以及与其他语言的差异 - Go语言从入门到实战

知识点 源码文件以_test结尾&#xff1a;xxx_test.go测试方法名以Test开头&#xff1a;func TestXXX(t *testing.T){…} 利用单元测试来写代码段&#xff0c;保存之后会自动运行程序返回结果&#xff0c;可以快速实践得到反馈。 编写测试程序 接下来练习一下&#xff0c;怎…...

Android 编译插桩操纵字节码

本文讲解如何编译插桩操纵字节码。 就使用 ASM 来实现简单的编译插桩效果&#xff0c;通过插桩实现在每一个 Activity 打开时输出相应的 log 日志。实现思路 过程主要包含两步&#xff1a; 1、遍历项目中所有的 .class 文件​ 如何找到项目中编译生成的所有 .class 文件&#…...

云原生的简单理解

一、何谓云原生&#xff1f; 一种构建和运行应用软件的方法 应用程序从设计之初即考虑到云的环境&#xff0c;原生为云而设计&#xff0c;在云上以最佳姿势运行&#xff0c;充分利用和发挥云平台的弹性分布式优势。 二、包括以下四个要素 采用容器化部署&#xff1a;实现云平…...

AVL Cruise 2020.1 安装教程

文章目录 安装包安装破解 安装包 链接&#xff1a;https://pan.baidu.com/s/1GxbeDj_SyvKFyPeTsstvTQ?pwd6666 提取码&#xff1a;6666 安装 安装文件&#xff1a; 双击setup.exe&#xff1a; 一直netx&#xff0c;中间要修改两次路径&#xff0c;第一次是安装位置&#xf…...

数组07-滑动窗口、HashMap

LeetCode——904. 水果成篮 你正在探访一家农场&#xff0c;农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示&#xff0c;其中 fruits[i] 是第 i 棵树上的水果 种类 。 你想要尽可能多地收集水果。然而&#xff0c;农场的主人设定了一些严格的规矩&#xff0c…...

【C++杂货店】类和对象(上)

【C杂货店】类和对象&#xff08;上&#xff09; 一、面向过程和面向对象初步认识二、类的引入三、类的定义四、类的访问限定符及封装4.1 访问限定符4.2 封装 五、类的作用域六、类的实例化七、类对象模型7.1 类对象的存储规则7.2 例题7.3结构体内存对齐规则 八、this指针8.2 t…...

K8S笔记

...

MySQL关于日期函数的使用-笔记

韩老师笔记 select current_time select CURRENT_DATE create table mes ( id int, content VARCHAR(255), send_time DATETIME ) select * from mes; insert into mes values(1,北京,CURRENT_DATE) insert into mes (id,send_time) values(2,CURRENT_TIME) insert into mes v…...

【postgresql 】 ERROR: “name“ is not supported as an alias

org.postgresql.util.PSQLException: ERROR: "name" is not supported as an alias 错误&#xff1a;不支持将“name”作为别名 SELECT real_name name FROM doc_user 加上 在关键词上加上 “” 示例&#xff1a; SELECT real_name "name" FROM do…...

都用HTTPS了,还能被查出浏览记录?

最近&#xff0c;群里一个刚入职的小伙因为用公司电脑访问奇怪的网站&#xff0c;被约谈了。他很困惑 —— 访问的都是HTTPS的网站&#xff0c;公司咋知道他访问了啥&#xff1f; 实际上&#xff0c;由于网络通信有很多层&#xff0c;即使加密通信&#xff0c;仍有很多途径暴露…...

vi配置文件.vimrc内容示例

1、.vimrc配置文件介绍 &#xff08;1&#xff09;.vimrc是vi编辑器的配置文件&#xff0c;里面可以对vi编译器做个性化配置&#xff1b; &#xff08;2&#xff09;.vimrc在用户目录下&#xff0c;每个用户有一个&#xff0c;类似于.bashrc文件&#xff0c;将下面的配置文件内…...

MacOS上的Pip和Python升级指南

在MacOS系统上&#xff0c;保持Pip和Python版本的最新状态对于顺利进行Python开发至关重要。通过升级Pip和Python&#xff0c;你可以享受到最新的功能、修复的bug以及提升的开发效率。本文将为你提供在MacOS上升级Pip和Python的详细指南&#xff0c;助你打造更强大的开发环境。…...

VB6.0实现修改EXE程序的图标

当你给一家公司做技术支持的时候&#xff0c;需求各种各样的&#xff0c;其中今天遇到就是要修改某个程序的图标&#xff0c;代码实现如下。 // q1016058890 群 214016721 //注 意&#xff1a;这个方法貌似只对有些EXE文件有效&#xff0c;这不是万能的方法&#xff0c;此…...

Python 编程基础 | 第二章-基础语法 | 2.3、for 语句

一、for 语句 1、循环语句 for循环的语法格式如下&#xff1a; for iterating_var in sequence:statements(s)例如&#xff1a; for ch in "hello world":print(ch)fruits ["banana", "apple", "mango"] for fruit in fruits:print(…...

linux下解决tomcat错误问题

错误一&#xff1a; Linux下Tomcat启动报错&#xff1a;Neither the JAVA_HOME nor the JRE_HOME environment variable is defined 原因&#xff1a;可能是Linux环境变了&#xff0c;需要在catalina.sh文件里指定JDK路径 解决方式&#xff1a; 在/bin/catalina.sh配置文件中加…...

PMP证书的价值如何?

2022年开始&#xff0c;PMP考试启用了新考纲&#xff0c;不光考试内容进行了大刀阔斧的改革&#xff0c;出题方式也进行了更新。除原有的PMBOK6和PMBOK7主考教材外&#xff0c;还增加了一本《敏捷实践指南》。 别小看新加的这本书&#xff0c;它虽然与PMBOK代表的预测法属于完…...

linux上mysql数据备份(全量备份策略+增量备份策略)

执行备份策略前&#xff0c;先做好scp命令的准备 解决思路&#xff1a; 生成SSH公钥/私钥后&#xff0c;您需要将公钥添加到服务器上&#xff0c;从而使服务器可以使用该公钥来验证您的身份。 生成SSH公钥/私钥的命令为 ssh-keygen -t rsa -b 4096什么都不用输入&#xff0c…...

PHP实现DFA算法,查找关键词

# 添加关键词 到全局字典dict里面 protected function addWord($strWord) {$len mb_strlen($strWord,UTF-8);$curNode &$this->dict;for ($index 0; $index < $len; $index) {$word mb_substr($strWord, $index, 1, UTF-8);if (!isset($curNode[$word])) {$curNo…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看

文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...