并发编程之JUC并发工具类下

目录

CyclicBarrier(回环栅栏或循环屏障)

特点

常用方法

CyclicBarrier应用场景

CyclicBarrier与CountDownLatch区别

Exchanger

特点

常用方法

Exchanger的应用场景

Phaser(阶段协同器)

特点

常用方法

Phaser的应用场景


CyclicBarrier(回环栅栏或循环屏障)

   CyclicBarrier是Java中的并发工具类,用于在多个线程之间创建一个屏障,所有线程必须在这个屏障前等待,一旦所有线程都到达了屏障,屏障才会打开,允许所有线程继续执行。它与 CountDownLatch的区别在于,CountDownLatch是一次性的,而CyclicBarrier可以被重用,因为一旦屏障打开,它会被重置,可以再次使用。以下是CyclicBarrier的一些特点以及常见使用方法:

特点

1. 等待线程数量: 创建 CyclicBarrier时需要指定等待的线程数量,所有线程都到达之后,屏障被打破,所有线程同时继续执行。

2. 重用性: 一旦所有线程都到达屏障点并释放,CyclicBarrier就可以被重置,以便下一轮使用。

3. 回调函数: 可以在所有线程到达屏障点后,指定一个Runnable任务来执行。

常用方法

1. 构造方法

public CyclicBarrier(int parties)
public CyclicBarrier(int parties, Runnable barrierAction)

parties:指定需要等待的线程数量。
barrierAction:在所有线程都到达屏障点后要执行的Runnable任务。

2. await 方法

public int await() throws InterruptedException, BrokenBarrierException

调用线程告诉CyclicBarrier它已经到达了屏障点,并等待其他线程到达。
当前线程会阻塞,直到所有线程都到达屏障点。
返回值表示当前线程是第几个到达屏障的,方便在回调函数中识别。

3. reset 方法

public void reset()

reset方法会将屏障恢复到初始状态,允许线程再次等待。这对于周期性地执行同步操作的情况非常有用。

CyclicBarrier应用场景

多线程任务:CyclicBarrier可以用于将复杂的任务分配给多个线程执行,并在所有线程完成工作后触发后续操 作。

数据处理:CyclicBarrier可以用于协调多个线程间的数据处理,在所有线程处理完数据后触发后续操作。

举例模拟人满发车如下:

import java.util.concurrent.*;public class CyclicBarrierDemo {public static void main(String[] args) {ExecutorService executorService = Executors.newFixedThreadPool(5);CyclicBarrier cyclicBarrier = new CyclicBarrier(5, () -> System.out.println("人齐了,准备发车"));for (int i = 0; i < 10; i++) {final int id = i + 1;executorService.submit(() -> {try {System.out.println(id + "号马上就到");int sleepMills = ThreadLocalRandom.current().nextInt(2000);Thread.sleep(sleepMills);System.out.println(id + "号到了,上车");cyclicBarrier.await();} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}});}executorService.shutdown();}
}
CyclicBarrier与CountDownLatch区别

CountDownLatch是一次性的,CyclicBarrier是可循环利用的。

CyclicBarrier在所有线程都到达屏障点后,可以执行一个可选的Runnable任务;CountDownLatch主要用于等待其他线程完成,没有特定的任务或动作。


Exchanger

        Exchanger是一种并发工具类,用于在两个线程之间交换数据。它提供了一个同步点,在这个同步点上,两个线程可以安全地交换数据。以下是Exchanger的一些特点以及常见使用方法:

特点

1. 用途:Exchanger用于实现两个线程之间的数据交换,允许两个线程在同步点上交换数据。

2. 双向交换:允许两个线程在一个点上进行数据交换,每个线程可以通过exchange()方法把自己的数据传递给对方。

3. 阻塞操作:如果一个线程在调用exchange()时没有找到另一个线程,它将会阻塞等待,直到另一个线程到达为止。

4. 数据传递:数据传递是按需进行的,当两个线程都到达同步点时才会进行交换。

常用方法

1.exchange(V x,):这个方法用于在两个线程之间交换数据。当一个线程调用这个方法时,它会被阻塞,直到另一个线程也调用了exchange()方法,然后两个线程可以交换数据,并且返回对方的数据。

2.exchange(V x, long timeout, TimeUnit unit):允许设置超时时间,在指定的时间内如果没有线程到达交换点,则抛出TimeoutException异常。

Exchanger的应用场景

数据交换:在多线程环境中,两个线程可以通过 Exchanger 进行数据交换。

数据采集:在数据采集系统中,可以使用 Exchanger 在采集线程和处理线程间进行数据交换。

import java.util.concurrent.Exchanger;public class ExchangerDemo {private static Exchanger<String> exchanger = new Exchanger<>();static String goods = "衣服";static String money = "200";public static void main(String[] args) throws InterruptedException {System.out.println("准备交易,一手交钱一手交货...");// 卖家new Thread(() -> {System.out.println("卖家到了,已经准备好货:" + goods);try {String receivedMoney = exchanger.exchange(goods);System.out.println("卖家收到钱:" + receivedMoney);} catch (InterruptedException e) {e.printStackTrace();}}).start();Thread.sleep(3000);// 买家new Thread(() -> {try {System.out.println("买家到了,已经准备好钱:" + money);String receivedGoods = exchanger.exchange(money);System.out.println("买家收到货:" + receivedGoods);} catch (InterruptedException e) {e.printStackTrace();}}).start();}
}

Phaser(阶段协同器)

  Phaser是一种并发工具类,用于协调多个线程的同步执行。它与CountDownLatch和CyclicBarrier类似,但提供了更灵活的功能。Phaser允许多个线程在特定的同步点上同步,并且可以动态地增加或减少参与同步的线程数量。

特点

1. 阶段同步:Phaser可以分成多个阶段,每个阶段可以有多个参与者线程。所有线程在达到同一个阶段之前将被阻塞,一旦所有线程都完成了当前阶段的任务,Phaser进入下一个阶段。

2. 动态注册:可以在Phaser运行时动态地注册新的参与者线程,也可以动态注销不再参与同步的线程。

3. 灵活的同步点:Phaser提供了arrive()和awaitAdvance()等方法,使线程能够在指定的同步点到达后继续执行。

4. 分层结构: Phaser支持分层结构,可以创建父Phaser,子Phaser可以独立运行并通过其父Phaser进行同步。

常用方法

构造方法
Phaser()  参与任务数0
Phaser(int parties)   指定初始参与任务数
Phaser(Phaser parent)   指定parent阶段器, 子对象作为一个整体加入parent对象, 当子对象中没有参与者时,会自动从parent对象解除注册
Phaser(Phaser parent,int parties)    集合上面两个方法

增减参与任务数方法
int register()
增加一个任务数,返回当前阶段号。
int bulkRegister(int parties) 增加指定任务个数,返回当前阶段号。
int arriveAndDeregister() 减少一个任务数,返回当前阶段号

到达、等待方法
int arrive() 
到达(任务完成),返回当前阶段号。
int arriveAndAwaitAdvance()  到达后等待其他任务到达,返回到达阶段号。
int awaitAdvance(int phase)  在指定阶段等待(必须是当前阶段才有效)
int awaitAdvanceInterruptibly(int phase)  阶段到达触发动作
int awaitAdvanceInterruptiBly(int phase,long timeout,TimeUnit unit)
protected boolean onAdvance(int phase,int registeredParties)
类似CyclicBarrier的触发命令,通过重写该方法来增加阶段到达动作,该方法返回true将终结Phaser对象

Phaser的应用场景

1. 多线程任务分配:Phaser 可以用于将复杂的任务分配给多个线程执行,并协调线程间的合作。
2. 多级任务流程:Phaser 可以用于实现多级任务流程,在每一级任务完成后触发下一级任务的开始。
3. 模拟并行计算:Phaser 可以用于模拟并行计算,协调多个线程间的工作。
4. 阶段性任务:Phaser 可以用于实现阶段性任务,在每一阶段任务完成后触发下一阶段任务的开始。

以模拟公司团建举例如下:

import java.util.concurrent.Phaser;public class CompanyOutingSimulation {public static void main(String[] args) throws InterruptedException {final int PARTICIPANTS = 5;Phaser phaser = new Phaser(PARTICIPANTS);System.out.println("阶段1: 公司集合");// 模拟阶段1: 到公司集合for (int i = 0; i < PARTICIPANTS; i++) {int participantId = i;Thread arrivalThread = new Thread(() -> {System.out.println("参与者 " + participantId + " 到公司集合");phaser.arriveAndAwaitAdvance(); // 等待其他线程到达阶段1});arrivalThread.start();}// 模拟阶段2: 出发去公园phaser.arriveAndAwaitAdvance(); // 所有线程到达阶段1后继续执行System.out.println("阶段2: 出发去公园");for (int i = 0; i < PARTICIPANTS; i++) {int participantId = i;Thread parkTripThread = new Thread(() -> {System.out.println("参与者 " + participantId + " 出发去公园");phaser.arriveAndAwaitAdvance(); // 等待其他线程到达阶段2});parkTripThread.start();}// 模拟阶段3: 去餐厅,有两个人离开phaser.arriveAndAwaitAdvance(); // 所有线程到达阶段2后继续执行System.out.println("阶段3: 出发去餐厅");// 模拟两个人离开for (int i = 0; i < 2; i++) {phaser.arriveAndDeregister(); // 离开的人取消注册System.out.println("有人离开,当前参与人数: " + phaser.getRegisteredParties());}// 模拟阶段4: 就餐,有三个人加入phaser.arriveAndAwaitAdvance(); // 所有线程到达阶段3后继续执行System.out.println("阶段4: 就餐");// 模拟三个人加入for (int i = 0; i < 3; i++) {phaser.register(); // 新加入的人注册System.out.println("有人加入,当前参与人数: " + phaser.getRegisteredParties());}}
}

       以上案例中,每个参与者都是一个线程,通过Phaser实现对四个阶段的同步。在第3阶段,两个人离开,通过phaser.arriveAndDeregister()​​​​​​​取消注册。在第4阶段,三个人加入,通过phaser.register()注册。

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

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

相关文章

1991-2022年A股上市公司股价崩盘风险指标数据

1991-2022年A股上市公司股价崩盘风险指标数据 1、时间&#xff1a;1991-2022年 2、来源&#xff1a;整理自csmar 3、指标&#xff1a;证券代码、交易年度、NCSKEW(分市场等权平均法)、NCSKEW(分市场流通市值平均法)、NCSKEW(分市场总市值平均法)&#xff1b; NCSKEW(综合市…

MySQL中的临键锁:深入理解与案例解析

一、引言 在数据库中&#xff0c;锁是一种非常重要的机制&#xff0c;用于管理并发操作&#xff0c;确保数据的一致性和完整性。MySQL支持多种类型的锁&#xff0c;其中临键锁&#xff08;Next-Key Locking&#xff09;是一种非常重要的锁策略&#xff0c;它结合了行锁和间隙锁…

【Spring 篇】JdbcTemplate:轻松驾驭数据库的魔法工具

欢迎来到数据库的奇妙世界&#xff0c;在这里&#xff0c;我们将一同揭开Spring框架中JdbcTemplate的神秘面纱。JdbcTemplate是Spring提供的一个简化数据库操作的工具&#xff0c;它为我们提供了一种轻松驾驭数据库的魔法。本篇博客将详细解释JdbcTemplate的基本使用&#xff0…

我的 AI 成长星球,邀请你加入

大家好啊&#xff0c;我是董董灿。 2023年终总结时我这个小白坚持写作一整年&#xff0c;赚了多少&#xff1f;提到了一点&#xff0c;2024希望自己创建一个免费星球。 其实一直就想弄一个高质量的 AI 知识交流平台&#xff0c;方便大家一起交流和学习&#xff0c;同时提高对 …

调整Hive查询临时内存大小的方法

文章目录 前言设置Hive查询的临时内存大小1、Hive 执行引擎内存参数2. Tez 引擎内存参数3. MapReduce 引擎内存参数 查询默认内存大小 总结 前言 在Hive中&#xff0c;调整临时内存大小是优化查询性能的关键一步。通过合理配置相关参数&#xff0c;可以使查询在处理大数据集时…

我的年度总结(大一程序员的自述)

呀哈喽&#xff0c;我是结衣。 我也来参加这个年度总结的话题咯&#xff0c;喜欢的话可以点个赞哦。 作为一个大一新生&#xff0c;我从1级的编程小白到了现在的2级编程小白。在7月份之前我可以说是完全不了解编程的一位新人&#xff0c;对应电脑的了解也就只会打游戏看电视和浏…

外贸企业为何要选择Yandex推广?

Yandex作为俄罗斯最大的搜索引擎&#xff0c;对于外贸企业的推广具有不可忽视的重要意义。随着全球市场的不断扩大和互联网的普及&#xff0c;越来越多的外贸企业开始将目光投向俄罗斯市场。而Yandex作为俄罗斯本土的搜索引擎巨头&#xff0c;拥有庞大的用户群体和广泛的市场覆…

Qt QCheckBox复选按钮控件

文章目录 1 属性和方法1.1 文本1.2 三态1.3 自动排他1.4 信号和槽 2 实例2.1 布局2.2 代码实现 Qt中的复选按钮类是QCheckBox它和单选按钮很相似&#xff0c;单选按钮常用在“多选一”的场景&#xff0c;而复选按钮常用在"多选多"的场景比如喜欢的水果选项中&#xf…

暴雨信息发布算力网络应用平台打造零感知算网服务新模式

为进一步优化算力网络应用服务能力和降低算力网络使用难度&#xff0c;暴雨信息突破基于算力网络的实例跨域协同与迁移、基于测试评估的应用度量和解构等技术&#xff0c;研发并推出算力网络应用平台。该系统通过提供一种即开即用、按需付费的零感知算网应用服务&#xff0c;使…

关于Redis的事务

关于Redis事务的学习&#xff0c;查了一些资料留存链接 腾讯二面&#xff1a;Redis 事务支持 ACID 么&#xff1f; Redis事务 高级Java程序员必问&#xff0c;Redis事务终极篇

【满分】【华为OD机试真题2023CD卷 JAVAJS】攀登者2

华为OD2023(C&D卷)机试题库全覆盖,刷题指南点这里 攀登者2 知识点数组 时间限制:1s 空间限制:32MB 限定语言:不限 题目描述: 攀登者喜欢寻找各种地图,并且尝试攀登到最高的山峰。 地图表示为一维数组,数组的索引代表水平位置,数组的高度代表相对海拔高度。其中数…

13年老鸟整理,自动化测试落地实施方案总结,看这篇就够了...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 一般来说&#xf…

RK平台计算GPIO对应的整型数

GPIO是比较常用的资源&#xff0c;比如说控制LED灯亮灭&#xff0c;控制LCD上电&#xff0c;控制模块的复位电路&#xff0c;做外设的中断脚等等&#xff0c;这些都有对GPIO的操作和使用&#xff0c;所以说&#xff0c;GPIO开发是驱动开发中必不可少的操作&#xff0c;而且也是…

如何轻松拿捏LIO-SAM?

LOAM是目前为止激光里程计(LO)领域最经典最广泛使用的方法&#xff0c;堪称LO领域的baseline&#xff0c;至今仍在KITTI数据集上名列前茅。但是它存在诸多问题&#xff0c;比如&#xff1a;它直接存储全局体素地图而不是局部地图&#xff0c;从而很难执行回环检测以修正漂移&am…

任务管理器的 top

文章目录 任务管理器的 top常规使用显示完整命令设置信息更新次数设置信息更新时间显示指定的进程信息指定用户的进程信息更多信息 任务管理器的 top top命令比较像Windows里面的任务管理器&#xff0c;提供一个动态实时的系统状态检测&#xff0c;可以检测实时显示内存、CPU、…

性能测试很简单-JMeter性能测试实践

最近破费买了一台服务器&#xff0c;准备搭建自己的网站&#xff0c;顺便将自己开发的一些测试小工具部署到服务器上&#xff0c;虽然机器配置一般&#xff0c;还是决定对服务器进行压测一番&#xff0c;看一下服务器性能如何。本次压测选择的工具是JMeter&#xff0c;这个工具…

Linux: 设置qmake的Qt版本

1、修改默认的qtchooser/default.conf // cct-app4:/usr/lib/x86_64-linux-gnu/qt-default/qtchooser % cat default.conf /usr/lib/x86_64-linux-gnu/qt4/bin /usr/lib/x86_64-linux-gnu // cct-app4:/usr/lib/x86_64-linux-gnu/qt-default/qtchooser 修改成对应的版本即可…

计算属性和监听属性,生命周期钩子,组件介绍

计算属性 # 计算属性是基于它们的依赖进行缓存的 # 计算属性只有在它的相关依赖发生改变时才会重新求值 # 计算属性就像Python中的property&#xff0c;可以把方法/函数伪装成属性 # 计算属性必须要有返回值 基本使用 <!DOCTYPE html> <html lang"en">…

[机缘参悟-122] :IT人如何认识自己的?自省、面试、考核、咨询?

目录 一、为什么要认识自己 二、认识自己的哪些方面&#xff1f; 三、如何认识自己 3.1 通过自省认识自己 3.2 通过面试认识自己 3.3 通过咨询认识自己 3.4 通过相亲认识自己 3.5 通过一段感情关系认识自己 一、为什么要认识自己 认识自己在人类的成长和心灵发展过程中…

Java jar文件变更jar或者xml方法

1. 解压jar文件 // 解压在同级 jar -xvf XXXX.jar2.解压后 在解压出来的文件中&#xff0c;找到修改的文件3.开始替换 jar -uvf0 XXXX.jar BOOT-INF4.校验方法 Java -jar XXXX.jar 是否正常启动