The Java concurrency API provides a synchronization utility that allows the interchange of data between two concurrent tasks. In more detail, the Exchanger class allows the definition of a synchronization point between two threads. When the two threads arrive to this point, they interchange a data structure so the data structure of the first thread goes to the second one and the data structure of the second thread goes to the first one.

This class may be very useful in a situation similar to the producer-consumer problem. This is a classic concurrent problem where you have a common buffer of data, one or more producers of data, and one or more consumers of data. As the Exchanger class only synchronizes two threads, you can use it if you have a producer-consumer problem with one producer and one consumer.

In this recipe, you will learn how to use the Exchanger class to solve the producer-consumer problem with one producer and one consumer.

1. First, let's begin by implementing the producer. Create a class named Producer and specify that it implements the Runnable interface.

  1. package com.packtpub.java7.concurrency.chapter3.recipe7.task;
  2.  
  3. import java.util.List;
  4. import java.util.concurrent.Exchanger;
  5.  
  6. /**
  7. * This class implements the producer
  8. *
  9. */
  10. public class Producer implements Runnable {
  11.  
  12. /**
  13. * Buffer to save the events produced
  14. */
  15. private List<String> buffer;
  16.  
  17. /**
  18. * Exchager to synchronize with the consumer
  19. */
  20. private final Exchanger<List<String>> exchanger;
  21.  
  22. /**
  23. * Constructor of the class. Initializes its attributes
  24. * @param buffer Buffer to save the events produced
  25. * @param exchanger Exchanger to syncrhonize with the consumer
  26. */
  27. public Producer (List<String> buffer, Exchanger<List<String>> exchanger){
  28. this.buffer=buffer;
  29. this.exchanger=exchanger;
  30. }
  31.  
  32. /**
  33. * Main method of the producer. It produces 100 events. 10 cicles of 10 events.
  34. * After produce 10 events, it uses the exchanger object to synchronize with
  35. * the consumer. The producer sends to the consumer the buffer with ten events and
  36. * receives from the consumer an empty buffer
  37. */
  38. @Override
  39. public void run() {
  40. int cycle=1;
  41.  
  42. for (int i=0; i<10; i++){
  43. System.out.printf("Producer: Cycle %d\n",cycle);
  44.  
  45. for (int j=0; j<10; j++){
  46. String message="Event "+((i*10)+j);
  47. System.out.printf("Producer: %s\n",message);
  48. buffer.add(message);
  49. }
  50.  
  51. try {
  52. /*
  53. * Change the data buffer with the consumer
  54. */
  55. buffer=exchanger.exchange(buffer);
  56. } catch (InterruptedException e) {
  57. e.printStackTrace();
  58. }
  59.  
  60. System.out.printf("Producer: %d\n",buffer.size());
  61.  
  62. cycle++;
  63. }
  64.  
  65. }
  66.  
  67. }

2. Second, implement the consumer. Create a class named Consumer and specify that it implements the Runnable interface.

  1. package com.packtpub.java7.concurrency.chapter3.recipe7.task;
  2.  
  3. import java.util.List;
  4. import java.util.concurrent.Exchanger;
  5.  
  6. /**
  7. * This class implements the consumer of the example
  8. *
  9. */
  10. public class Consumer implements Runnable {
  11.  
  12. /**
  13. * Buffer to save the events produced
  14. */
  15. private List<String> buffer;
  16.  
  17. /**
  18. * Exchager to synchronize with the consumer
  19. */
  20. private final Exchanger<List<String>> exchanger;
  21.  
  22. /**
  23. * Constructor of the class. Initializes its attributes
  24. * @param buffer Buffer to save the events produced
  25. * @param exchanger Exchanger to syncrhonize with the consumer
  26. */
  27. public Consumer(List<String> buffer, Exchanger<List<String>> exchanger){
  28. this.buffer=buffer;
  29. this.exchanger=exchanger;
  30. }
  31.  
  32. /**
  33. * Main method of the producer. It consumes all the events produced by the Producer. After
  34. * processes ten events, it uses the exchanger object to synchronize with
  35. * the producer. It sends to the producer an empty buffer and receives a buffer with ten events
  36. */
  37. @Override
  38. public void run() {
  39. int cycle=1;
  40.  
  41. for (int i=0; i<10; i++){
  42. System.out.printf("Consumer: Cycle %d\n",cycle);
  43.  
  44. try {
  45. // Wait for the produced data and send the empty buffer to the producer
  46. buffer=exchanger.exchange(buffer);
  47. } catch (InterruptedException e) {
  48. e.printStackTrace();
  49. }
  50.  
  51. System.out.printf("Consumer: %d\n",buffer.size());
  52.  
  53. for (int j=0; j<10; j++){
  54. String message=buffer.get(0);
  55. System.out.printf("Consumer: %s\n",message);
  56. buffer.remove(0);
  57. }
  58.  
  59. cycle++;
  60. }
  61.  
  62. }
  63.  
  64. }

3. Finally, implement the main class of the example by creating a class named Core and add the main() method to it.

  1. package com.packtpub.java7.concurrency.chapter3.recipe7.core;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import java.util.concurrent.Exchanger;
  6.  
  7. import com.packtpub.java7.concurrency.chapter3.recipe7.task.Consumer;
  8. import com.packtpub.java7.concurrency.chapter3.recipe7.task.Producer;
  9.  
  10. /**
  11. * Main class of the example
  12. *
  13. */
  14. public class Main {
  15.  
  16. /**
  17. * Main method of the example
  18. * @param args
  19. */
  20. public static void main(String[] args) {
  21.  
  22. // Creates two buffers
  23. List<String> buffer1=new ArrayList<>();
  24. List<String> buffer2=new ArrayList<>();
  25.  
  26. // Creates the exchanger
  27. Exchanger<List<String>> exchanger=new Exchanger<>();
  28.  
  29. // Creates the producer
  30. Producer producer=new Producer(buffer1, exchanger);
  31. // Creates the consumer
  32. Consumer consumer=new Consumer(buffer2, exchanger);
  33.  
  34. // Creates and starts the threads
  35. Thread threadProducer=new Thread(producer);
  36. Thread threadConsumer=new Thread(consumer);
  37.  
  38. threadProducer.start();
  39. threadConsumer.start();
  40.  
  41. }
  42.  
  43. }

The consumer begins with an empty buffer and calls Exchanger to synchronize with the producer. It needs data to consume. The producer begins its execution with an empty buffer. It creates 10 strings, stores it in the buffer, and uses the exchanger to synchronize with the consumer.

At this point, both threads (producer and consumer) are in Exchanger and it changes the data structures, so when the consumer returns from the exchange() method, it will have a buffer with 10 strings. When the producer returns from the exchange() method, it will have an empty buffer to fill again. This operation will be repeated 10 times.

If you execute the example, you will see how producer and consumer do their jobs concurrently and how the two objects interchange their buffers in every step. As it occurs with other synchronization utilities, the first thread that calls the exchange() method was put to sleep until the other threads arrived.

Exchanger, Changing data between concurrent tasks的更多相关文章

  1. 未能从程序集 C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Data.Entity.Build.Tasks.dll 加载任务“EntityClean”

    问题: 未能从程序集 C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Data.Entity.Build.Tasks.dll 加载任务“Entity ...

  2. Fork and Join: Java Can Excel at Painless Parallel Programming Too!---转

    原文地址:http://www.oracle.com/technetwork/articles/java/fork-join-422606.html Multicore processors are ...

  3. java.util.concurrent.Exchanger应用范例与原理浅析--转载

    一.简介   Exchanger是自jdk1.5起开始提供的工具套件,一般用于两个工作线程之间交换数据.在本文中我将采取由浅入深的方式来介绍分析这个工具类.首先我们来看看官方的api文档中的叙述: A ...

  4. java Concurrent包学习笔记(六):Exchanger

    一.概述 Exchanger 是一个用于线程间协作的工具类,Exchanger用于进行线程间的数据交换,它提供一个同步点,在这个同步点,两个线程可以交换彼此的数据.这两个线程通过exchange 方法 ...

  5. 并发编程-concurrent指南-交换机Exchanger

    java.util.concurrent包中的Exchanger类可用于两个线程之间交换信息.可简单地将Exchanger对象理解为一个包含两个格子的容器,通过exchanger方法可以向两个格子中填 ...

  6. Java Concurrency - Concurrent Collections

    Data structures are a basic element in programming. Almost every program uses one or more types of d ...

  7. JUC——线程同步辅助工具类(Exchanger,CompletableFuture)

    Exchanger交换空间 如果现在有两个线程,一个线程负责生产数据,另外一个线程负责消费数据,那么这个两个线程之间一定会存在一个公共的区域,那么这个区域的实现在JUC包之中称为Exchanger. ...

  8. Java并发编程原理与实战二十九:Exchanger

    一.简介 前面三篇博客分别介绍了CyclicBarrier.CountDownLatch.Semaphore,现在介绍并发工具类中的最后一个Exchange.Exchange是最简单的也是最复杂的,简 ...

  9. 并发新构件之Exchanger:交换器

    Exchanger:JDK描述:可以在对中对元素进行配对和交换的线程的同步点.每个线程将条目上的某个方法呈现给 exchange 方法,与伙伴线程进行匹配,并且在返回时接收其伙伴的对象.Exchang ...

随机推荐

  1. JDBC 的基本步骤

    JDBC 的基本步骤: 一.导入mysql-connector-java-x.x.x-bin.jar后: 二.代码 1. 注册驱动(三种方式)2. 创建一个连接对象(三种方式) 3. 创建一个sql语 ...

  2. Polymorphism

    多态定义(百度百科):多态(Polymorphism)按字面的意思就是“多种状态”.在面向对象语言中,接口的多种不同的实现方式即为多态.引用Charlie Calverts对多态的描述 ——多态性是允 ...

  3. other

    1.http://handlebarsjs.com/ 2.grunt

  4. 我眼中的PM

    我眼中的PM 1 我眼中的PM 1.1 人云“一个管理,半个专家”,我说“一个管理,两个专家” 如今,我发现我们不得不面对这样一个现实——角色兼职.我习惯上把项目分为三类:性命攸关的项目(涉及到人身安 ...

  5. html样式表极大地提高了工作效率

    样式表极大地提高了工作效率 样式表定义如何显示 HTML 元素,就像 HTML 3.2 的字体标签和颜色属性所起的作用那样.样式通常保存在外部的 .css 文件中.通过仅仅编辑一个简单的 CSS 文档 ...

  6. 【不积跬步,无以致千里】mysql 多行合并函数

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...

  7. [C语言(VC)] 打造自己的键盘记录器 (zaroty)

    说起键盘记录,想必很多朋友都用过网上流传的一些键盘记录软件吧,但是有没有想过自己写一个呢?也许你会想:会不会很复杂啊?我可以很负责的告诉你,写键盘记录是很简单的.你所需要的仅仅是懂得一些C语言的DLL ...

  8. PHP str_replace() 函数

    定义和用法 str_replace() 函数使用一个字符串替换字符串中的另一些字符. 语法 str_replace(find,replace,string,count) 参数 描述 find 必需.规 ...

  9. CCNA 例题精选

    3. Refer to the exhibit. Whichtwo statements are true about interVLAN routing in the topology that i ...

  10. Android手机上判断网络运营商

    我们想获取手机的运营商信息.通常都会去调用系统的TelephonyManager类的取数据.但是很多时候可能取不到卡的信息(例如双卡手机和 一些特殊卡),这样就区别不了运营商了.但是有时候我们的需求要 ...