exchanger_如何通过示例在Java中使用Exchanger

exchanger

大家好,如果您在并发Java应用程序中工作,那么您可能听说过java.util.concurrent包的Exchanger类。 Java中的Exchanger是Java 1.5中与CountDownLatch , CyclicBarrier和Semaphores一起引入的另一个并发或同步实用程序。 顾名思义, Exchanger允许两个线程在集合点或集合点见面并交换数据。 的
java.util.Exchanger是一个参数类,它定义并保存要交换的对象的类型。 它有一个重载的方法,称为
exchange() ,用于在线程之间交换对象。 这是一种阻塞方法,这意味着线程将调用 exchange()方法在交换点等待,直到另一个线程到达。 一旦另一个线程到达,两个线程都交换对象并从该方法返回。 交换方法的重载版本接受其他 TimeUnit对象并等待直到超时。

顺便说一句,您还可以中断在交换点等待其他参与者的线程。 与CountDownLatchCyclicBarrierSemaphoreExchanger实用程序只能同步两个线程,这使其非常适合解决经典的生产者-消费者问题 。

在本Java Concurrency教程中,您将通过使用Exchanger实现生产者-消费者设计模式来学习如何在Java中使用Exchanger。 顺便说一句,我假设您熟悉Java编程语法和语义,如果您是Java的完整入门者,那么您可能会很难理解这个示例。

Exchanger类是一个易于理解和使用的简单同步实用程序。 在最后的两个并发教程中,我们使用了wait和notify解决了生产者使用者(请参阅此处 ),还使用BlockingQueue实现了生产者-消费者 ,现在该使用Exchanger来实现了。

在此Java并发性教程中, 我们将创建一个生产者和一个消费者线程 ,它们将使用Exchanger实用程序类交换缓冲区。

通常,这是Exchanger的工作方式:

1.首先创建一个Exchange对象,例如Exchanger<Deque<Long>> stringExchanger = new Exchanger<>() ; 这定义了线程之间将交换什么类型的对象。 在这种情况下,两个线程将交换包含长值的Deque对象。

2.当线程A准备交换其缓冲区或对象时,它将调用
Exchanger.exchange()方法。 这是一种阻塞方法 , 线程A将被阻塞,直到线程B到来并将其对象传输到线程A 为止,否则线程A被中断或超时。

3.线程B准备就绪时,它还会调用exchange()方法。 现在,线程A和B互相交换对象,并从交换方法返回。

4.交换完成后,线程A具有线程B的对象,反之亦然。

同样,我想强调Java并发技能的重要性,并敦促每个Java开发人员花一些时间来掌握Java并发类。

带有Exchanger并发的Java程序

 import java.util.ArrayDeque;  import java.util.Deque;  import java.util.concurrent.Exchanger;   /** * Exchanger Example in Java. Exchanger allows two Threads to meet at exchange * point and exchange data structure or objects. In this Java program, exchanger * is used to exchange buffer between producer and consumer.  * @author Javin Paul  */   public class JavaExchangerTutorail {    public static void main(String args[]) throws InterruptedException {   //Creating Exchanger to exchange String object with other thread final Exchanger> exchanger = new Exchanger>();   Thread producer = new Thread( "Producer : " ){  @Override public void run(){  ArrayDeque(); Deque stack = new ArrayDeque();  //producer thread insert elments into stack while (stack.isEmpty()) { 
 stack.add(System.nanoTime()% 1000 ); //if stack is not empty then exchange it to consumer thread  try {  System.out.println(Thread.currentThread().getName() + " ready to exchange : " + stack); 
 <br> 
 // Exchanger return other Thread's object stack = exchanger.exchange(stack); System.out.println(Thread.currentThread().getName() + " got : " + stack);  } catch (InterruptedException ie) { ie.printStackTrace(); } (InterruptedException ie) { ie.printStackTrace(); }  }  }  };    Thread consumer = new Thread( "Consumer : " ){  @Override  public void run(){  ArrayDeque(); Deque stack = new ArrayDeque();   //consumer thread takes object from stack and prints  do { //if stack is empty then exchange it to producer for refill try {  System.out.println(Thread.currentThread().getName() + " ready to exchange : " + stack); stack = exchanger.exchange(stack); System.out.println(Thread.currentThread().getName() + " got : " + stack); stack.remove();  } catch (InterruptedException ie) { ie.printStackTrace(); } (InterruptedException ie) { ie.printStackTrace(); }  } while (stack.isEmpty()) ;    }  };    producer.start(); 
 <br> 
 //sleeping before starting consumer to give producer time to produce Thread.sleep( 1000 ); 
 consumer.start();    }     }     Output:   Producer : ready to exchange : [ 247 ]   Consumer : ready to exchange : []   Producer : got : []   Consumer : got : [ 247 ]   Producer : ready to exchange : [ 692 ]   Consumer : ready to exchange : []   Consumer : got : [ 692 ]   Consumer : ready to exchange : []   Producer : got : [] 
 <br> 

代码和输出说明

如果看上面的示例,所有代码都在main方法内部。 之所以使Exchanger实例成为最终实例,是因为我们要从匿名内部类访问它们,并且只能从匿名内部类访问最终局部变量。

后来,我们创建了两个线程, ProducerConsumer 。 生产者检查队列,如果队列为空,则将当前nano time的最后三位相加并调用exchange()方法。

现在,直到消费者线程到达交换点,我的意思是直到生产者线程调用exchange()方法,生产者线程才会被阻塞。

消费者到达后,双方互相交换堆栈并从exchange()方法返回。 这时,生产者有一个空的消费者堆栈,而消费者有一个非空的生产者堆栈,我的意思是,他们有彼此的对象

为了理解哪个线程正在交换哪个堆栈,我们在每个线程交换之前和之后打印堆栈的内容。 如果您查看输出,这是不言自明的。

顺便提一下,与线程一样,不能保证以相同的顺序获得输出。 在第三次迭代中,您可以看到使用者具有一个已清空的堆栈,甚至可以在安排生产者线程并从交换方法返回之前,准备交换空堆栈。

这就是如何在Java中使用Exchanger的全部内容。 交换器类是一个很好的简单同步工具,非常适合于协调两个线程。 应该使用交换器来实现具有一个生产者和一个消费者的生产者-消费者模式。 如果您想了解有关Java并发类的更多信息,建议您检查以下资源:

进阶学习

完整的Java Masterclass Java多线程,并发和性能优化 Java并发实践–本书 将并发和多线程应用于常见的Java模式

您可能喜欢的其他Java并发文章

  • 2020 Java开发人员路线图 ( 路线图 )
  • Java并发之前发生了什么? ( 回答 )
  • 10个Java多线程和并发最佳实践( 文章 )
  • Java中的前50个多线程和并发问题( 问题 )
  • 掌握Java并发性的5大书籍( 书籍 )
  • 10个面向初学者和中级开发者的免费Java课程( 课程 )
  • 如何避免Java中的死锁? ( 回答 )
  • 了解Java程序中的数据和代码流( 回答 )
  • Java Concurrency in Practice是否在2020年仍然有效( 回答 )
  • Java中CyclicBarrier和CountDownLatch之间的区别? ( 回答 )
  • 10个技巧,成为2020年的一个更好的Java开发( 提示 )
  • 如何使用wait-notify在Java中进行线程间通信? ( 回答 )
  • 深入学习Java多线程的前5门课程( 课程 )

感谢您到目前为止阅读本文。 如果您喜欢此Java并发教程,请与您的朋友和同事分享。 如果您有任何疑问或反馈,请留下笔记。

PS –如果您是Java世界的新手,并且想与Concurrency一起学习核心概念,但是想找一些免费的入门课程,那么您也可以在Udemy上查看此免费的Java Multithreading课程 。 这也是学习Java并发性的一门很好的免费课程。

翻译自: https://www.javacodegeeks.com/2020/05/how-to-use-exchanger-in-java-with-example.html

exchanger

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

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

相关文章

Java Enumeration接口与Iterator接口

一、Enumeration接口 Enumeration接口中定义了一些方法&#xff0c;通过这些方法可以枚举&#xff08;一次获得一个&#xff09;对象集合中的元素。 这种传统接口已被迭代器取代&#xff0c;虽然Enumeration 还未被遗弃&#xff0c;但在现在代码中已经被很少使用了。尽管如此&a…

java国际化——日期和时间+排序

【0】README 1&#xff09; 本文部分文字描述转自 core java volume 2 &#xff0c; 测试源代码均为原创&#xff0c; 旨在理解 java国际化——日期和时间排序 的基础知识 &#xff1b; 【1】日期和时间 1&#xff09;当格式化日期和时间时&#xff0c;需要考虑4个与 Locale …

jvm 垃圾收集算法_JVM垃圾收集和优化

jvm 垃圾收集算法总览 在对系统进行性能相关问题的故障排除时&#xff0c;内存优化是一个需要深入分析每个系统在内存中存储的内容&#xff0c;存储时间和访问方式的场所。 这篇文章是要对背景信息进行注释&#xff0c;并在此工作中要注意一些要点&#xff0c;这些工作要针对基…

数据库SQL索引

一、索引的意义 表中创建索引&#xff0c;以便更加快速高效地查询数据。 用户无法看到索引&#xff0c;它们只能被用来加速搜索/查询。 注释&#xff1a;更新一个包含索引的表需要比更新一个没有索引的表花费更多的时间&#xff0c;这是由于索引本身也需要更新。因此&#x…

java国际化——消息格式化+文本文件和字符集

【0】README 1&#xff09; 本文部分文字描述转自 core java volume 2 &#xff0c; 测试源代码均为原创&#xff0c; 旨在理解 java国际化——消息格式化文本文件和字符集 的基础知识 &#xff1b; 2&#xff09; 由于本文涉及到的源代码都比较简单&#xff0c;所以直接将全…

java 8 新功能详解_Java 8和Java 14之间的新功能

java 8 新功能详解从版本9开始&#xff0c;Java每6个月就有一次新功能&#xff0c;因此很难跟踪这些新更改。 互联网上的大多数信息都描述了最近2个Java版本之间的变化。 但是&#xff0c;如果您的情况与我相似&#xff0c;则说明您使用的不是Java的最新版本&#xff0c;而是使…

Tomcat配置虚拟内存

一、Tomcat启动参数JAVA_OPTS参数说明   -server 启用jdk 的 server 版&#xff1b;   -Xms java 虚拟机初始化时的堆最小内存&#xff1b;   -Xmx java 虚拟机可使用堆的最大内存&#xff1b;   -XX: PermSize 非堆内存永久保留区域   -XX:MaxPermS…

ISO语言代码和国家代码+Locale常量+ISO货币符号

【1】ISO语言代码和国家代码 【2】Locale常量 【3】ISO货币符号

djl和ljl_使用Spring Boot和DJL进行深度学习

djl和ljl总览 这是Spring Boot上的另一篇文章 &#xff0c;该文章将展示如何使用Deep Java Library &#xff08;DJL&#xff09;构建示例Web应用程序&#xff0c; Deep Java Library &#xff08;DJL&#xff09;是Java的开源深度学习库&#xff0c;用于诊断X射线图像上的COVI…

java BigDecimal八种舍入模式

一、BigDecimal介绍java.math.BigDecimal不可变的immutable、任意精度的有符号十进制数。BigDecimal 由任意精度的整数非标度值和32位的整数标度(scale)组成。标度(scale)如果为零或正数&#xff0c;则标度是小数点后的位数。如果为负数&#xff0c;则将该数的非标度值乘以10的…

java国际化——资源包

【0】README 1&#xff09; 本文部分文字描述转自 core java volume 2 &#xff0c; 旨在理解 java国际化——资源包 的基础知识 &#xff1b; 2&#xff09; 本文源代码idea 转自&#xff1a; &#xff08;利用properties 文件进行国际化&#xff09;https://docs.oracle.co…

ui自动化测试测试报告_您需要了解的有关UI测试的所有信息

ui自动化测试测试报告让我们从一个问题开始。 用户在网站上进行互动的第一件事是什么&#xff1f; 接口&#xff0c;当然。 网站的外观是在用户身上产生“第一印象”的第一件事。 交互式Web应用程序可以为用户带来成败&#xff0c;这就是为什么越来越多的人选择对其Web应用程序…

Tomcat解决HTTP GET中文乱码

一、中文乱码原因 Tomcat默认是按ISO-8859-1进行URL解码&#xff0c;ISO-8859-1并未包括中文字符&#xff0c;中文字符不能被正确解析了。 二、配置编码 在tomcat的conf/server.xml下的connetor属性中增加URIEncoding或者useBodyEncodingForURI属性 &#xff08;1&#xff0…

NanoHTTPD web server的一个简单荔枝

【0】README 0.1&#xff09;本文旨在演示一个简单荔枝&#xff0c;以说明如何使用 NanoHTTPD web server 和 浏览器访问 该server的效果 -------------------------------------------------------------- App.java public class App extends NanoHTTPD {public App() thr…

throwable_您想了解的所有Throwable

throwable本文是有关异常的教程。 但不是通常的一种。 其中有许多内容可以告诉您异常的含义&#xff0c;如何抛出异常&#xff0c;捕获异常&#xff0c;已检查异常和运行时异常之间的区别&#xff0c;等等。 没有必要了。 这对您来说也很无聊。 如果没有&#xff0c;那么请阅读…

Linux Tomcat安装

一、linux 安装软件的步骤 &#xff08;1&#xff09;下载软件的压缩包 &#xff08;2&#xff09;解压到指定的目录 &#xff08;3&#xff09;配置环境变量 &#xff0c;配置PATH&#xff08;在任意目录启动&#xff0c;这PATH可以省略&#xff0c;若不配置只有安装目录才…

java分布式对象(RMI+部署使用RMI的程序)

【0】README 1&#xff09;本文文字转自 core java volume 2&#xff0c; 旨在学习 java 分布式对象的相关知识&#xff1b; 2&#xff09; RMI 的实例程序为原创&#xff1b; 3&#xff09; RMI部署步骤的测试用例&#xff0c;参见 http://blog.csdn.net/pacosonswjtu/arti…

java 创建uri_使用UriBuilder快速创建URI

java 创建uri如果您有权访问JAX-RS API和项目中的实现&#xff08;很多&#xff09;&#xff0c;则可以使用JAX-RS的UriBuilder通过使用可解析占位符的构建器模式方便地创建URI。 看下面的例子&#xff1a; String host System.getProperty( "host" , "localh…

Tomcat 服务自动启动

一、配置/etc/rc.local rc.local是linux启动init之后执行的脚本。 sudo vi /etc/rc.local 添加如下一行 /home/myuser/software/apache-tomcat-7.0.29/bin/startup.sh&#xff08;脚本绝对路径&#xff09; 二、sysv-rc-conf 工具配置 1、安装 sysv-rc-conf sudo apt-get …

java分布式对象RMI应用测试用例

【0】README 0.1&#xff09;本文旨在对http://blog.csdn.net/PacosonSWJTU/article/details/50705192 中的代码进行实践&#xff08;如何部署一个使用RMI框架的程序以进行远程调用&#xff09;&#xff1b; 0.2&#xff09; for complete source code, please visit https…