java.util.concurrent包中的Exchanger类可用于两个线程之间交换信息。可简单地将Exchanger对象理解为一个包含两个格子的容器,通过exchanger方法可以向两个格子中填充信息。当两个格子中的均被填充时,该对象会自动将两个格子的信息交换,然后返回给线程,从而实现两个线程的信息交换。
另外需要注意的是,Exchanger类仅可用作两个线程的信息交换,当超过两个线程调用同一个exchanger对象时,得到的结果是随机的,exchanger对象仅关心其包含的两个“格子”是否已被填充数据,当两个格子都填充数据完成时,该对象就认为线程之间已经配对成功,然后开始执行数据交换操作。

Exchanger可以在两个线程之间交换数据,只能是2个线程,他不支持更多的线程之间互换数据。

Exchanger是在两个任务之间交换对象的栅栏,当这些任务进入栅栏时,它们各自拥有一个对象。当他们离开时,它们都拥有之前由对象持有的对象。

它典型的应用场景是:一个任务在创建对象,这些对象的生产代价很高昂,而另一个任务在消费这些对象。通过这种方式,可以有更多的对象在被创建的同时被消费。

public class ExchangerRunnable implements Runnable{
private Exchanger<String> exchanger;
private String data;
private int random;
public ExchangerRunnable(Exchanger exchanger,String data,int random){
this.exchanger = exchanger;
this.data = data;
this.random = random;
} @Override
public void run() {
System.out.println(Thread.currentThread().getName()+",数据:"+data);
try {
TimeUnit.SECONDS.sleep(random);
String data_new = exchanger.exchange(data);
System.out.println(Thread.currentThread().getName()+",数据:"+data_new);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Main {
public static void main(String[] args) {
//交换机
Exchanger exchanger = new Exchanger(); ExchangerRunnable exchangerRunnable = new ExchangerRunnable(exchanger,"aa",3);
ExchangerRunnable exchangerRunnable1 = new ExchangerRunnable(exchanger,"bb",10); new Thread(exchangerRunnable).start();
new Thread(exchangerRunnable1).start();
}
}

结果:

Thread-0,数据:aa
Thread-1,数据:bb
Thread-0,数据:bb
Thread-1,数据:aa

注意:

1.当线程A调用Exchange对象的exchange()方法后,他会陷入阻塞状态,直到线程B也调用了exchange()方法,然后以线程安全的方式交换数据,之后线程A和B继续运行。

2.多个线程时,有且只有两个线程进入数据交换。

源码地址:https://github.com/qjm201000/concurrent_exchanger.git

并发编程-concurrent指南-交换机Exchanger的更多相关文章

  1. 并发编程-concurrent指南-原子操作类-AtomicInteger

    在java并发编程中,会出现++,--等操作,但是这些不是原子性操作,这在线程安全上面就会出现相应的问题.因此java提供了相应类的原子性操作类. 1.AtomicInteger

  2. 并发编程-concurrent指南-线程池ExecutorService的实例

    1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() { @Override public void run() { ...

  3. 并发编程-concurrent指南-计数器CountDownLatch

    java.util.concurrent.CountDownLatch 是一个并发构造,它允许一个或多个线程等待一系列指定操作的完成. CountDownLatch 以一个给定的数量初始化.count ...

  4. 并发编程-concurrent指南-ConcurrentMap

    ConcurrentMap 是个接口,你想要使用它的话就得使用它的实现类之一. ConcurrentMap,它是一个接口,是一个能够支持并发访问的java.util.map集合: 在原有java.ut ...

  5. 并发编程-concurrent指南-阻塞双端队列-链阻塞双端队列LinkedBlockingDeque

    LinkedBlockingDeque是双向链表实现的阻塞队列.该阻塞队列同时支持FIFO和FILO两种操作方式,即可以从队列的头和尾同时操作(插入/删除): 在不能够插入元素时,它将阻塞住试图插入元 ...

  6. 并发编程-concurrent指南-阻塞队列-链表阻塞队列LinkedBlockingQueue

    LinkedBlockingQueue是一个基于链表的阻塞队列. 由于LinkedBlockingQueue实现是线程安全的,实现了先进先出等特性,是作为生产者消费者的首选. LinkedBlocki ...

  7. 并发编程-concurrent指南-原子操作类-AtomicLong

    可以用原子方式更新的 long 值.有关原子变量属性的描述,请参阅 java.util.concurrent.atomic 包规范.AtomicLong 可用在应用程序中(如以原子方式增加的序列号), ...

  8. 并发编程-concurrent指南-原子操作类-AtomicBoolean

    类AtomicBoolean

  9. 并发编程-concurrent指南-ReadWriteLock-ReentrantReadWriteLock(可重入读写锁)

    几个线程都申请读锁,都能获取: import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantRea ...

随机推荐

  1. Laravel 5.2 中多用户认证实现(前台和后台登录)

    Laravel 5.2中多用户认证支持,即同时允许不同数据表用户(如前台用户.后台用户.app用户等)登录认证.下面我们就来简单介绍多用户登录及注册功能实现. 1.生成认证脚手架 首先我们使用Lara ...

  2. POJ读书笔记2.1 —— 鸡兔笼带

    http://blog.csdn.net/pipisorry/article/details/36433305 问题描写叙述  一个笼子里面关了鸡和兔子(鸡有2仅仅脚.兔子有4仅仅脚.没有例外). 已 ...

  3. jqmobi api 详细解说

    0.$().get()得到是相应的元素. 如: $elem=$(".panal").get(0));   //得到了第一个panal类的元素 $elem_id = $elem.id ...

  4. WCF服务的IIS托管(应用程序)

    基本思路 建立与发布参考网站托管 在IIS中某一网站,选择添加应用程序   访问服务uri:http://localhost/wcfAppTest/Service1.svcwcfAppTest/Ser ...

  5. Android之运行时相机权限和联系人权限获取

    原文:Android之运行时相机权限和联系人权限获取 本文链接:http://blog.csdn.net/qq_16628781/article/details/61623502 Android之运行 ...

  6. 【C#】WPF的xaml中定义的Trigger为什么有时候会不管用,如Border的MouseOver之类的

    原文:[C#]WPF的xaml中定义的Trigger为什么有时候会不管用,如Border的MouseOver之类的 初学WPF,知道一些控件可以通过定义Style的Trigger改变要显示的样式,但是 ...

  7. C# dotnetcore2.0结合Selenium搜索网页

    using System; using OpenQA.Selenium; using OpenQA.Selenium.Chrome; namespace ConsoleApp_Selenium { c ...

  8. 队列读取器代理 遇到错误 Row handle is invalid

    原文:队列读取器代理 遇到错误 Row handle is invalid 今天测试在发布中更改表名称,在发布数据库更改后重新发布这个表. 但是原来的表在订阅没有删除,不小心插入数据到原表中,队列读取 ...

  9. Android Contact 导入导出 vcf格式(不依赖第三方库)

    Android sdk 支持vcf处理的(忘记最低哪个版本开始支持的了,可以查一查) 备注:此代码来自Stack Overflow(原地址找不到了,o(╥﹏╥)o) 1. 导出联系人为vcf格式 Co ...

  10. Android零基础入门第33节:Android事件处理概述

    原文:Android零基础入门第33节:Android事件处理概述 通过对Android基本组件的学习,也有接触少部分Android的事件处理,比如按钮的点击事件.选框的状态切换事件. 一.Andro ...