1.实现原理

Exchanger(交换者)是一个用于线程间协作的工具类。Exchanger用于进行线程间的数据交换。它提供一个同步点,在这个同步点两个线程可以交换彼此的数据。这两个线程通过exchange方法交换数据, 如果第一个线程先执行exchange方法,它会一直等待第二个线程也执行exchange,当两个线程都到达同步点时,这两个线程就可以交换数据,将本线程生产出来的数据传递给对方。因此使用Exchanger的重点是成对的线程使用exchange()方法,当有一对线程达到了同步点,就会进行交换数据。因此该工具类的线程对象是成对的。

Exchanger类提供了两个方法,String exchange(V x):用于交换,启动交换并等待另一个线程调用exchange;String exchange(V x,long timeout,TimeUnit unit):用于交换,启动交换并等待另一个线程调用exchange,并且设置最大等待时间,当等待时间超过timeout便停止等待。

2.实例讲解

通过以上的原理,可以知道使用Exchanger类的核心便是exchange()方法的使用,接下来通过一个例子来使的该工具类的用途更加清晰。该例子主要讲解的是前段时间NBA交易截止日的交易。

package concurrent;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.*;
public class ExchangerDemo {public static void main(String[] args) {ExecutorService executor = Executors.newCachedThreadPool();final Exchanger exchanger = new Exchanger();executor.execute(new Runnable() {String data1 = "克拉克森,小拉里南斯";@Overridepublic void run() {nbaTrade(data1, exchanger);}});executor.execute(new Runnable() {String data1 = "格里芬";@Overridepublic void run() {nbaTrade(data1, exchanger);}});executor.execute(new Runnable() {String data1 = "哈里斯";@Overridepublic void run() {nbaTrade(data1, exchanger);}});executor.execute(new Runnable() {String data1 = "以赛亚托马斯,弗莱";@Overridepublic void run() {nbaTrade(data1, exchanger);}});executor.shutdown();}private static void nbaTrade(String data1, Exchanger exchanger) {try {System.out.println(Thread.currentThread().getName() + "在交易截止之前把 " + data1 + " 交易出去");Thread.sleep((long) (Math.random() * 1000));String data2 = (String) exchanger.exchange(data1);System.out.println(Thread.currentThread().getName() + "交易得到" + data2);} catch (InterruptedException e) {e.printStackTrace();}}
}

运行程序,得到如下结果:

pool-1-thread-1在交易截止之前把 克拉克森,小拉里南斯 交易出去
pool-1-thread-2在交易截止之前把 格里芬 交易出去
pool-1-thread-3在交易截止之前把 哈里斯 交易出去
pool-1-thread-4在交易截止之前把 以赛亚托马斯,弗莱 交易出去
pool-1-thread-2交易得到哈里斯
pool-1-thread-3交易得到格里芬
pool-1-thread-4交易得到克拉克森,小拉里南斯
pool-1-thread-1交易得到以赛亚托马斯,弗莱

以上例子可以看出两个都调用exchange()方法的线程会进行交换数据。接下来假设线程数目只有奇数个,观察情况:

如以下代码,将第四个线程注释掉。

package concurrent;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.*;
public class ExchangerDemo {public static void main(String[] args) {ExecutorService executor = Executors.newCachedThreadPool();final Exchanger exchanger = new Exchanger();executor.execute(new Runnable() {String data1 = "克拉克森,小拉里南斯";@Overridepublic void run() {nbaTrade(data1, exchanger);}});executor.execute(new Runnable() {String data1 = "格里芬";@Overridepublic void run() {nbaTrade(data1, exchanger);}});executor.execute(new Runnable() {String data1 = "哈里斯";@Overridepublic void run() {nbaTrade(data1, exchanger);}});//        executor.execute(new Runnable() {
//            String data1 = "以赛亚托马斯,弗莱";
//
//            @Override
//            public void run() {
//                nbaTrade(data1, exchanger);
//            }
//        });executor.shutdown();}private static void nbaTrade(String data1, Exchanger exchanger) {try {System.out.println(Thread.currentThread().getName() + "在交易截止之前把 " + data1 + " 交易出去");Thread.sleep((long) (Math.random() * 1000));String data2 = (String) exchanger.exchange(data1);System.out.println(Thread.currentThread().getName() + "交易得到" + data2);} catch (InterruptedException e) {e.printStackTrace();}}
}

运行程序,得到如下结果:

pool-1-thread-1在交易截止之前把 克拉克森,小拉里南斯 交易出去
pool-1-thread-2在交易截止之前把 格里芬 交易出去
pool-1-thread-3在交易截止之前把 哈里斯 交易出去
pool-1-thread-3交易得到格里芬
pool-1-thread-2交易得到哈里斯

由结果可知,线程2和线程3进行了交换数据,而线程1一直等待与它交换数据的线程调用exchange,但是只有3个线程,所以会一直等待。

因此,当两个线程之间出现数据交换的情况,可以使用Exchanger工具类实现数据交换。注意exchange方法的含义,以及触发数据交换的条件。

Exchanger的工作原理及实例相关推荐

  1. Webservice工作原理及实例

    Web Service工作原理及实例 一.Web Service基本概念 Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intran ...

  2. linux traceroute命令详解_详解Linux系统路由跟踪指令traceroute语法、工作原理和实例说明...

    概述 traceroute我们可以知道信息从你的计算机到互联网另一端的主机是走的什么路径.当然每次数据包由某一同样的出发点(source)到达某一同样的目的地(destination)走的路径可能会不 ...

  3. 高速光耦(PS8101,TLP112A,TLP109)基本工作原理应用实例

    PS8101,TLP112A 是采用5pin SOP封装的高速光耦合器,速率达到 1 Mbps. PS8101由Renesas生产,TLP112A和TLP109由Toshiba生产.      采用S ...

  4. mysql布隆过滤器源码_通过实例解析布隆过滤器工作原理及实例

    布隆过滤器 布隆过滤器是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure),特点是高效地插入和查询,可以用来告诉你 "一定不存在或者可能存在& ...

  5. 布隆过滤算法c语言,通过实例解析布隆过滤器工作原理及实例

    布隆过滤器 布隆过滤器是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure),特点是高效地插入和查询,可以用来告诉你 "一定不存在或者可能存在& ...

  6. ArcGIS教程:Zonal相关的工作原理及实例

    区域分析工具概述 "区域分析"工具用于对属于每个输入区域的所有像元执行分析,输出是执行计算后的结果.虽然区域可以定义为具有特定值的单个区域,但它也可由具有相同值的多个断开元素或区域 ...

  7. WebService 工作原理及实例教程

    一.WebService到底是什么? 先来看下标准的定义:Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统 ...

  8. [转载] Web Service工作原理及实例

    一.Web Service基本概念 Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量 ...

  9. 分层结构的生活例子_详解软件分层架构设计、工作原理、实例以及具体架构

    概述 今天的内容主要来自<软件架构模式>第一章,觉得还不错,所以分享给大家. 分层架构 分层架构是一种很常见的架构模式,它也叫N层架构.这种架构是大多数Jave EE应用的实际标准,因此很 ...

最新文章

  1. Alibaba 之 Nacos
  2. Bzoj3550 [ONTAK2010]Vacation
  3. oracle union 最多_用户来稿:我就是那个在优买计划赚钱最多的男人
  4. Redis中bitmap的妙用
  5. android线程栈默认大小,线程的默认最大堆栈大小 - Internet Information Services | Microsoft Docs...
  6. Redis内存分析工具
  7. React开发(149):ant design控制是否必填
  8. 阿里云释放数据能力 开启大数据元年
  9. Maven知识- repositories
  10. php 二维数组根据键值合并二维数组_php数组实现根据某个键值将相同键值合并生成新二维数组的方法详解...
  11. oracle 循环select查询的结构集,执行insert到指定表保存
  12. python用jieba模块分词实现关键词提取
  13. 在网页在播放flv格式的视频
  14. poj2594 Treasure Exploration 二分匹配之最小路径覆盖+传递闭包
  15. 题目 1842: 对局匹配
  16. mysql数据库如何授权_MySQL数据库学习笔记 ---- 数据库授权
  17. php 编写桌面程序_PHP能开发桌面应用吗?
  18. 把故事收回到一杯茶里,不知不觉,茶已经凉了
  19. 从输出海外吃鸡游戏浅谈创新
  20. WEB开发文档2 总结

热门文章

  1. 支付宝集五福!新玩法竟然可以不用还花呗!
  2. Linux--RH254---rh254exam
  3. idea启动nacos,idea连接指定数据库,Idea中Http Client 工具的应用
  4. linux 修改文件明,linux修改文件名你肯定不知道可以这样操作
  5. Android——Framework目录分析及系统启动过程以及目录简介
  6. 命令行简单使用一下PMD【win和linux双系统】【JAVA静态代码审查工具】
  7. wows 线段树+差分
  8. 锐龙R9 4900H和R9 4900HS哪个好
  9. 数据库连接池原理解析
  10. 超全面常用的数据库优化方案