exchanger_如何通过示例在Java中使用Exchanger
exchanger
大家好,如果您在并发Java应用程序中工作,那么您可能听说过java.util.concurrent
包的Exchanger类。 Java中的Exchanger是Java 1.5中与CountDownLatch , CyclicBarrier和Semaphores一起引入的另一个并发或同步实用程序。 顾名思义, Exchanger
允许两个线程在集合点或集合点见面并交换数据。 的
java.util.Exchanger
是一个参数类,它定义并保存要交换的对象的类型。 它有一个重载的方法,称为
exchange()
,用于在线程之间交换对象。 这是一种阻塞方法,这意味着线程将调用 exchange()
方法在交换点等待,直到另一个线程到达。 一旦另一个线程到达,两个线程都交换对象并从该方法返回。 交换方法的重载版本接受其他 TimeUnit对象并等待直到超时。
顺便说一句,您还可以中断在交换点等待其他参与者的线程。 与CountDownLatch
, CyclicBarrier
或Semaphore
, Exchanger
实用程序只能同步两个线程,这使其非常适合解决经典的生产者-消费者问题 。
在本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
实例成为最终实例,是因为我们要从匿名内部类访问它们,并且只能从匿名内部类访问最终局部变量。
后来,我们创建了两个线程, Producer和Consumer 。 生产者检查队列,如果队列为空,则将当前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
exchanger_如何通过示例在Java中使用Exchanger相关推荐
- 如何通过示例使用Java中的Exchanger
大家好,如果您在并发Java应用程序中工作,那么您可能听说过java.util.concurrent包的Exchanger类. Java中的Exchanger是Java 1.5中与CountDownL ...
- java 根据类名示例化类_如何使用示例从Java中的类路径加载资源
java 根据类名示例化类 Java中的类路径不仅用于加载.class文件,而且还可以用于加载资源,例如属性文件,图像,图标,缩略图或任何二进制内容. Java提供了API来将这些资源读取为Input ...
- 如何使用示例从Java中的类路径加载资源
Java中的类路径不仅用于加载.class文件,而且还可以用于加载资源,例如属性文件,图像,图标,缩略图或任何二进制内容. Java提供了API来将这些资源读取为InputStream或URL. 假设 ...
- 如何通过示例在Java中使用CopyOnWriteArraySet
CopyOnWriteArraySet是CopyOnWriteArrayList类的弟弟. 这些是专用集合类,这些类是在JDK 1.5上添加的,以及它们最流行的表亲ConcurrentHashMap ...
- 代码示例:Java中定义数组的三种方式
在Java中,数组的定义有三种方式,其基本语法格式如下: 数组类型[] 数组名 = new 数组类型[数组长度]; 数组类型[] 数组名 = new 数组类型[]{数组元素0,数组元素1,...}; ...
- 【java】Java 中的 Exchanger 线程同步使用方法 线程之间交换数据
1.概述 转载:https://www.pdai.tech/md/java/thread/java-thread-x-juc-tool-exchanger.html 视频参考:https://www. ...
- Java i18n - Java中的国际化
Java i18n - Java中的国际化 Java或Java i18n的国际化是一个非常重要的特性.Java通过资源包提供国际化(i18n)支持. Java的国际化 为了使您的应用程序支持不同的语言 ...
- 【高并发】java中的CAS,你需要知道的东西
1.概述 转载:添加链接描述 从网站计数器实现中一步步引出CAS操作 介绍java中的CAS及CAS可能存在的问题 悲观锁和乐观锁的一些介绍及数据库乐观锁的一个常见示例 使用java中的原子操作实现网 ...
- 【ssl认证、证书】java中的ssl语法API说明(SSLContext)、与keytool 工具的联系
文章目录 1. 前言 java中的ssl语法与keytool 工具的联系 2. SSLContext的体系 2.1 KeyStore 2.1.1 通过证书库文件创建: 2.1.2 随机生成自签名证书库 ...
最新文章
- 斯坦科维奇洲际篮球冠军杯
- 2021年下信息系统项目管理师报考和考试时间
- 《Adobe Premiere Pro CC经典教程》——14.6 特殊颜色效果
- select2 属性标签整理
- 作者:何波(1989-),男,就职于中国信息通信研究院互联网法律研究中心
- Java数据结构Map List Set及Queue相关的类图
- 又搞事!雷军郑重宣告:小米9才是骁龙855全球真首发
- ApplicationContextAware使用理解
- 汪文君PowerMock实战视频
- 【单片机课程合集】摩尔吧魔鬼集训营,单片机尽情学!
- 南京大学计算机系副教授名单,2018年度国际“人工智能10大新星”名单公布:南京大学俞扬副教授国内高校入选者...
- 国美易卡存储引擎和事务的关系(国美易卡)
- matlab2c使用c++实现matlab函数系列教程-kron函数
- 各种说明方法的答题格式_说明方法作用答题格式
- Log4j史诗级漏洞,从原理到实战,只用3个实例讲明白
- 鼠标右键转圈圈_鼠标点击右键后一直转圈圈
- 利用梆梆加固逻辑漏洞取巧脱壳
- JAVA基础 之 System
- 做微信还是做APP,两种选择的不同风险
- android三级联动、四级联动(地区选择)
热门文章
- Acwing 271. 杨老师的照相排列
- 牛客网【每日一题】5月19日题目精讲 比赛
- [HEOI2013] SAO(dp + 组合数 + 前缀和)
- 【刷题记录】排列dp
- 【数位DP】CF 54C,509C,431D,628D,855E,1245F,95D
- # CF1572B Xor of 3(构造)
- jzoj3919-志愿者【换根法,线段树,树形dp】
- POJ3468-A Simple Problem with Integers【线段树,树状数组,分块】
- Flowable学习笔记(一、入门)
- JavaFX官方教程(三)之JavaFX示例应用程序入门