java-Exchanger详解
1.概述
java.util.concurrent.Exchanger。这在Java中作为两个线程之间交换对象的公共点。
2.Exchanger简介
Exchanger
类可用于在两个类型为T的线程之间共享对象。该类仅提供了一个重载的方法exchange(T t)。
当调用exchanger
时,它会等待成对的另一个线程也调用它。在这一点上,第二个线程发现第一个线程正在等待其对象。线程交换它们持有的对象并发出交换信号,然后它们可以返回。
让我们看一个例子,以理解两个线程之间使用Exchanger
进行消息交换:
@Test
public void givenThreads_whenMessageExchanged_thenCorrect() {Exchanger<String> exchanger = new Exchanger<>();Runnable taskA = () -> {try {String message = exchanger.exchange("from A");assertEquals("from B", message);} catch (InterruptedException e) {Thread.currentThread().interrupt();throw new RuntimeException(e);}};Runnable taskB = () -> {try {String message = exchanger.exchange("from B");assertEquals("from A", message);} catch (InterruptedException e) {Thread.currentThread().interrupt();throw new RuntimeException(e);}};CompletableFuture.allOf(runAsync(taskA), runAsync(taskB)).join();}
在这里,我们有两个线程使用共同的Exchanger
交换彼此之间的消息。让我们看一个例子,在这个例子中,我们从主线程与一个新线程交换对象:
@Test
public void givenThread_WhenExchangedMessage_thenCorrect() throws InterruptedException, ExecutionException {Exchanger<String> exchanger = new Exchanger<>();Runnable runner = () -> {try {String message = exchanger.exchange("from runner");assertEquals("to runner", message);} catch (InterruptedException e) {Thread.currentThread().interrupt();throw new RuntimeException(e);}};CompletableFuture<Void> result = runAsync(runner);String msg = exchanger.exchange("to runner");assertEquals("from runner", msg);result.join();}
请注意,我们需要先启动runner
线程,然后在主线程中调用exchange()
。
还要注意,如果第二个线程在超时时间内未达到交换点,第一个线程的调用可能会超时。第一个线程应等待多长时间可以使用重载的exchange(T t, long timeout, TimeUnit timeUnit)
来控制。
3.无GC数据交换
Exchanger
可以用于创建通过一个线程向另一个线程传递数据的管道类型的模式。
private static final int BUFFER_SIZE = 100;@Testpublic void givenData_whenPassedThrough_thenCorrect() throws InterruptedException, ExecutionException {Exchanger<Queue<String>> readerExchanger = new Exchanger<>();Exchanger<Queue<String>> writerExchanger = new Exchanger<>();int counter = 0;Runnable reader = () -> {Queue<String> readerBuffer = new ConcurrentLinkedQueue<>();while (true) {readerBuffer.add(UUID.randomUUID().toString());if (readerBuffer.size() >= BUFFER_SIZE) {try {readerBuffer = readerExchanger.exchange(readerBuffer);} catch (InterruptedException e) {Thread.currentThread().interrupt();throw new RuntimeException(e);}}}};Runnable processor = () -> {Queue<String> processorBuffer = new ConcurrentLinkedQueue<>();Queue<String> writerBuffer = new ConcurrentLinkedQueue<>();try {processorBuffer = readerExchanger.exchange(processorBuffer);while (true) {writerBuffer.add(processorBuffer.poll());if (processorBuffer.isEmpty()) {try {processorBuffer = readerExchanger.exchange(processorBuffer);writerBuffer = writerExchanger.exchange(writerBuffer);} catch (InterruptedException e) {Thread.currentThread().interrupt();throw new RuntimeException(e);}}}} catch (InterruptedException e) {Thread.currentThread().interrupt();throw new RuntimeException(e);}};Runnable writer = () -> {Queue<String> writerBuffer = new ConcurrentLinkedQueue<>();try {writerBuffer = writerExchanger.exchange(writerBuffer);while (true) {System.out.println(writerBuffer.poll());if (writerBuffer.isEmpty()) {writerBuffer = writerExchanger.exchange(writerBuffer);}}} catch (InterruptedException e) {Thread.currentThread().interrupt();throw new RuntimeException(e);}};CompletableFuture.allOf(runAsync(reader), runAsync(processor), runAsync(writer)).get();}
在这里,我们有三个线程:reader
、processor
和writer
。它们共同作为一个单一的管道,在它们之间交换数据。
readerExchanger
在reader
和processor
线程之间共享,而writerExchanger
在processor
和writer
线程之间共享。
请注意,此处的示例仅用于演示。在创建无限循环时务必小心while(true)
。另外,为保持代码的可读性,我们省略了一些异常处理。
通过重用缓冲区来交换数据的这种模式允许减少垃圾回收。exchange
方法返回相同的队列实例,因此这些对象不会被垃圾回收。与任何阻塞队列不同,Exchanger
不会创建任何用于保存和共享数据的节点或对象。
创建这样的管道类似于Disruptor
模式,其中一个关键区别是,Disruptor
模式支持多个生产者和消费者,而Exchanger
可以在一对生产者和消费者之间使用。
4.总结
因此,Java中的Exchanger是什么,它是如何工作的,我们看到了如何使用Exchanger
类。此外,我们创建了一个管道,并演示了线程之间无GC
的数据交换。
相关文章:
java-Exchanger详解
1.概述 java.util.concurrent.Exchanger。这在Java中作为两个线程之间交换对象的公共点。 2.Exchanger简介 Exchanger类可用于在两个类型为T的线程之间共享对象。该类仅提供了一个重载的方法exchange(T t)。 当调用exchanger时,它会等待成对的另一个线程也调用它…...
‘再战千问:启程你的提升之旅‘,如何更好地提问?
例如,很多时候我们提出一些问题,然而通义千问提供的答案,并非完全符合我们的期望。这并非由于通义千问的智能程度不足,而是提问者的“提问技巧”尚未掌握得当。 难道提问还需要讲究艺术性吗?确实如此。今天,…...
java SSM社区文化服务管理系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计
一、源码特点 java SSM社区文化服务管理系统是一套完善的web设计系统(系统采用SSM框架进行设计开发,springspringMVCmybatis),对理解JSP java编程开发语言有帮助,系统具有完整的 源代码和数据库,系统主…...
go执行静态二进制文件和执行动态库文件
目的和需求:部分go的核心文件不开源,例如验证,主程序核心逻辑等等 第一个想法,把子程序代码打包成静态文件,然后主程序执行 子程序 package mainimport ("fmt""github.com/gogf/gf/v2/os/gfile"…...
通过示例解释序列化和反序列化-Java
序列化和反序列化是Java(以及通常的编程)中涉及将对象转换为字节流,以及反之的过程。当你需要传输或存储对象的状态时特别有用,比如将其通过网络发送或持久化到文件中。 序列化: 定义:序列化是将对象的状…...
k8s源码阅读环境配置
源码阅读环境配置 k8s代码的阅读可以让我们更加深刻的理解k8s各组件的工作原理,同时提升我们Go编程能力。 IDE使用Goland,代码阅读环境需要进行如下配置: 从github上下载代码:https://github.com/kubernetes/kubernetes在GOPATH目…...
Java JDBC整合(概述,搭建,PreparedStatement和Statement,结果集处理)
一、JDBC的概述: JDBC:是一种执行sql语句的Java APL,可以为多种关系类型数据库提供统一访问,它由一组用Java语言编写的类和接口组成。有了JDBC,Java人员只需要编写一次程序就可以访问不同的数据库。 JDBC APL…...
Nginx 负载均衡集群 节点健康检查
前言 正常情况下,nginx 做反向代理负载均衡的话,如果后端节点服务器宕掉的话,nginx 默认是不能把这台服务器踢出 upstream 负载集群的,所以还会有请求转发到后端的这台服务器上面,这样势必造成网站访问故障 注&#x…...
uniapp 多轴图,双轴图,指定哪几个数据在哪个轴上显示
这里使用的在这里导入, 秋云 ucharts echarts 高性能跨全端图表组件 - DCloud 插件市场 这里我封装成一个组件,自适应的,可以直接复制到自己的项目中 <template><qiun-data-charts type"mix":opts"opts":cha…...
Kotlin 协程 supervisorScope {} 运行崩溃解决
前言 简单介绍supervisorScope函数,它用于创建一个使用了 SupervisorJob 的 coroutineScope, 该作用域的特点:抛出的异常,不会 连锁取消 同级协程和父协程。 看过很多 supervisorScope {} 文档的使用,我照抄一摸一样…...
【Spring 篇】JdbcTemplate:轻松驾驭数据库的魔法工具
欢迎来到数据库的奇妙世界,在这里,我们将一同揭开Spring框架中JdbcTemplate的神秘面纱。JdbcTemplate是Spring提供的一个简化数据库操作的工具,它为我们提供了一种轻松驾驭数据库的魔法。本篇博客将详细解释JdbcTemplate的基本使用࿰…...
Web开发SpringBoot SpringMVC Spring的学习笔记(包含开发常用工具类)
开发框架学习笔记 一.Spring SpringMVC SpringBoot三者的联系SpringMVC工作原理 二.SpringBoot的学习2.1 注解2.1.1 SpringBoot的核心注解2.1.2 配置导入注解(简化Spring配置写XML的痛苦)Configuration和Bean(人为注册Spring 的 Bean)Import(补)ImportResource(补)AutowiredQua…...
微服务下的SpringSecurity认证端
从三板斧开始微服务下的SpringSecurity开始 一、引入组件包 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId> </dependency> 二、创建适配器 AuthorizationServerConfig…...
苹果电脑菜单栏应用管理软件Bartender 4 mac软件特点
Bartender mac是一款可以帮助用户更好地管理和组织菜单栏图标的 macOS 软件。它允许用户隐藏和重新排列菜单栏图标,从而减少混乱和杂乱。 Bartender mac软件特点 菜单栏图标隐藏:Bartender 允许用户隐藏菜单栏图标,只在需要时显示。这样可以…...
笙默考试管理系统-MyExamTest----codemirror(65)
笙默考试管理系统-MyExamTest----codemirror(65) 目录 一、 笙默考试管理系统-MyExamTest----codemirror 二、 笙默考试管理系统-MyExamTest----codemirror 三、 笙默考试管理系统-MyExamTest----codemirror 四、 笙默考试管理系统-MyExamTest---…...
git在本地创建dev分支并和远程的dev分支关联起来
文章目录 git在本地创建dev分支并和远程的dev分支关联起来1. 使用git命令2. 使用idea2.1 先删除上面建的本地分支dev2.2 通过idea建dev分支并和远程dev分支关联 3. 查看本地分支和远程分支的关系 git在本地创建dev分支并和远程的dev分支关联起来 1. 使用git命令 git checkout…...
【C++】深入了解构造函数之初始化列表
目录 一、再谈构造函数 1、引入 1)构造函数体赋值 2)不同成员变量赋值 2、初始化列表 一、再谈构造函数 1、引入 1)构造函数体赋值 在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值…...
差分--差分数组快速计算L到R值相加后的数组
目录 差分:思路代码: 原题链接 差分: 输入一个长度为 n 的整数序列。 接下来输入 m 个操作,每个操作包含三个整数 l,r,c ,表示将序列中 [l,r] 之间的每个数加上 c 。 请你输出进行完所有操作后的序列。 输入格式 第…...
《NLP入门到精通》栏目导读(01/2)
一、说明 栏目《NLP入门到精通》本着从简到难得台阶式学习过度。将自然语言处理得知识贯穿过来。本栏目得前导栏目是《深度学习》、《pytorch实践》,因此,读者需要一定得深度学习基础,才能过度到此栏目内容。 二、博客建设理念 本博客基地,将建成人工智能领域的参考资料库;…...
three.js实现电子围栏效果(纹理贴图)
three.js实现电子围栏效果(纹理贴图) 实现步骤 围栏的坐标坐标转换为几何体顶点,uv顶点坐标加载贴图,移动 图例 代码 <template><div class"app"><div ref"canvesRef" class"canvas-…...
DHSP和DNS
一、服务程序 1.1DHCP定义 DHCP(动态主机配置协议)是一个局域网的网络协议。指的是由服务器控制一段IP地址范围,客户机登录服务器时就可以自动获得服务器分配的IP地址和子网掩码。默认情况下,DHCP作为Windows Server的一个服务组…...
Python冒号的解释
1. “没什么首次没有为第二个,跳了三个”。它得到的切片序列的每一个第三个项目。 扩展片是你想要的。新在Python 2.3 2. Python的序列切片地址可以写成[开始:结束:一步]和任何启动,停止或结束可以被丢弃。a[::3]是每第三个序列。…...
uniapp微信小程序投票系统实战 (SpringBoot2+vue3.2+element plus ) -后端鉴权拦截器实现
锋哥原创的uniapp微信小程序投票系统实战: uniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )_哔哩哔哩_bilibiliuniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )共计21条视频…...
固乔快递查询助手:批量、快速、全面的快递信息查询软件
在快递行业飞速发展的今天,如何高效、准确地掌握快递信息成为了很多人的需求。而固乔快递查询助手正是解决这一难题的利器。 固乔快递查询助手是一款专注于快递信息查询的软件,支持多家主流快递公司查询。用户只需输入单号,即可快速查询到实时…...
C#,归并排序算法(Merge Sort Algorithm)的源代码及数据可视化
归并排序 归并算法采用非常经典的分治策略,每次把序列分成n/2的长度,将问题分解成小问题,由复杂变简单。 因为使用了递归算法,不能用于大数据的排序。 核心代码: using System; using System.Text; using System.Co…...
Linux的网络服务DHCP
一.了解DHCP服务 1.1 DHCP定义 DHCP(动态主机配置协议)是一个局域网的网络协议。指的是由服务器控制一段IP地址范围,客户机登录服务器时就可以自动获得服务器分配的IP地址和子网掩码。默认情况下,DHCP作为Windows Server的一个服…...
【小沐学CAD】开源Assimp库导入三维模型(C++、Python)
文章目录 1、简介2、下载编译3、代码测试3.1 C3.2 pyassimp(Python) 结语 1、简介 https://github.com/assimp/assimp Open Asset Import Library 是一个库,用于将各种 3D 文件格式加载为共享的内存格式。它支持 40 多种用于导入的文件格式和…...
RT-Thread:SPI万能驱动 SFUD 驱动Flash W25Q64,通过 STM32CubeMX 配置 STM32 SPI 驱动
关键词:SFUD,FLASH,W25Q64,W25Q128,STM32F407 说明:RT-Thread 系统 使用 SPI万能驱动 SFUD 驱动 Flash W25Q64,通过 STM32CubeMX 配置 STM32 SPI 驱动。 提示:SFUD添加后的存储位置 1.打开RT-Thread Sett…...
Python学习笔记-使用Anaconda+VSCode配置开发环境
文章目录 概述一、安装Anaconda1.1 下载软件1.2 安装anaconda1.3 配置环境 二、配置虚拟环境2.1 使用conda创建一个新的虚拟环境2.1.1 使用search指令查看支持的python的版本:2.1.2 使用create创建指定版本的虚拟环境:2.1.3 使用env list查看虚拟环境列表…...
RabbitMQ的关键概念解析
RabbitMQ 是一个广泛使用的开源消息代理,它允许应用程序通过复杂的路由和存储机制来交换数据。理解 RabbitMQ 的核心概念对于有效地使用它至关重要。以下是 RabbitMQ 的一些关键概念及其工作流程: 关键概念 生产者(Producer) 生产…...
dw做视频网站/百度付费推广
http://poj.org/problem?id2559 题意都懂,给出数列h1,h2,...hn。代表n个宽为1,高为hi的矩形,求最大连续的矩形面积。 思路:对于每个矩形,当然高已经决定,我们思考它的宽可以为多少。很容易得出它的宽可以向…...
做网站seo优化/东莞seo计费
常用命令: profile文件立即生效:source /etc/profile source /home/kituser/.bash_profile 修改文件夹子文件权限:chmod -R 777 /home/kituser/jdk1.6.0_37 查看位置:whereis java、which java 防火墙:service iptable…...
厦门定制型网站建设/万网域名注册官网阿里云
内联函数 以inline修饰的函数叫做内联函数,编译时C编译器会在调用内联函数的地方展开,没有函数压 栈的开销,内联函数提升程序运行的效率 #define Fun(x,y) x*y #define N 10 int Mul(int x, int y) {return x*y; } int main() {cout <<…...
杭州有哪些做网站的公司/南京市网站
以下是zen cart 首页程序的修改。根据各个文件修改不同的功能。 首页界面://include/templates/zccn/common/tpl_main_page.php首页主样式表://include/templates/zccn/css/schinese_stylesheet.css 首页左边栏目:/includes/templates/templa…...
wordpress xiu底部广告/武汉百度推广外包
char c cv::waitKey(20);while (1)//读视频的循环{if(c ) { cv::waitKey(0);}if(cq | | cQ){break;}}...
微信上可以做网站吗/seo属于技术还是营销
FAIL_ON_SYMBOL_HASH_OVERFLOW 这个类型不存在。 问题的原因是jar包版本冲突。这个是在jackson的 since 2.4版本的包里面才有。2.3之前的版本是没有得。 这个存在2.4及以上才出现的,所以,实际运行的项目中jackson的jar冲突了。 我这儿的问题是flume的l…...