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交易截止日的交易。
-
-
import java.util.concurrent.Exchanger;
-
import java.util.concurrent.ExecutorService;
-
import java.util.concurrent.Executors;
-
-
public class ExchangerDemo {
-
-
public static void main(String[] args) {
-
ExecutorService executor = Executors.newCachedThreadPool();
-
-
final Exchanger exchanger = new Exchanger();
-
executor.execute(new Runnable() {
-
String data1 = "克拉克森,小拉里南斯";
-
-
-
-
-
nbaTrade(data1, exchanger);
-
-
-
-
-
executor.execute(new Runnable() {
-
-
-
-
-
nbaTrade(data1, exchanger);
-
-
-
-
executor.execute(new Runnable() {
-
-
-
-
-
nbaTrade(data1, exchanger);
-
-
-
-
executor.execute(new Runnable() {
-
String data1 = "以赛亚托马斯,弗莱";
-
-
-
-
nbaTrade(data1, exchanger);
-
-
-
-
-
-
-
private static void nbaTrade(String data1, Exchanger exchanger) {
-
-
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) {
-
-
-
-
运行程序,得到如下结果:
-
pool-1-thread-1在交易截止之前把 克拉克森,小拉里南斯 交易出去
-
pool-1-thread-2在交易截止之前把 格里芬 交易出去
-
pool-1-thread-3在交易截止之前把 哈里斯 交易出去
-
pool-1-thread-4在交易截止之前把 以赛亚托马斯,弗莱 交易出去
-
-
-
pool-1-thread-4交易得到克拉克森,小拉里南斯
-
pool-1-thread-1交易得到以赛亚托马斯,弗莱
以上例子可以看出两个都调用exchange()方法的线程会进行交换数据。接下来假设线程数目只有奇数个,观察情况:
如以下代码,将第四个线程注释掉。
-
-
import java.util.concurrent.Exchanger;
-
import java.util.concurrent.ExecutorService;
-
import java.util.concurrent.Executors;
-
-
public class ExchangerDemo {
-
-
public static void main(String[] args) {
-
ExecutorService executor = Executors.newCachedThreadPool();
-
-
final Exchanger exchanger = new Exchanger();
-
executor.execute(new Runnable() {
-
String data1 = "克拉克森,小拉里南斯";
-
-
-
-
-
nbaTrade(data1, exchanger);
-
-
-
-
-
executor.execute(new Runnable() {
-
-
-
-
-
nbaTrade(data1, exchanger);
-
-
-
-
executor.execute(new Runnable() {
-
-
-
-
-
nbaTrade(data1, exchanger);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
private static void nbaTrade(String data1, Exchanger exchanger) {
-
-
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) {
-
-
-
-
运行程序,得到如下结果:
-
pool-1-thread-1在交易截止之前把 克拉克森,小拉里南斯 交易出去
-
pool-1-thread-2在交易截止之前把 格里芬 交易出去
-
pool-1-thread-3在交易截止之前把 哈里斯 交易出去
-
-
由结果可知,线程2和线程3进行了交换数据,而线程1一直等待与它交换数据的线程调用exchange,但是只有3个线程,所以会一直等待。
因此,当两个线程之间出现数据交换的情况,可以使用Exchanger工具类实现数据交换。注意exchange方法的含义,以及触发数据交换的条件。
下面看代码例子:
package thread.exchanger;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExchangerTest {
public static void main(String[] args) {
ExecutorService pool = Executors.newCachedThreadPool();//线程缓存池
final Exchanger<String> exchanger = new Exchanger<String>();//用于一对线程的交换
pool.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep((long)(Math.random()*10000));
String data1 = "白粉";
System.out.println("线程"+Thread.currentThread().getName()+"已经到达交换地点,准备拿"+data1+"交换!");
data1 = exchanger.exchange(data1);//进行交换返回交换后的物品
System.out.println("线程"+Thread.currentThread().getName()+"交换成功,拿到"+data1);
} catch (Exception e) {
e.printStackTrace();
}
}
});
pool.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep((long)(Math.random()*10000));
String data2 = "钱";
System.out.println("线程"+Thread.currentThread().getName()+"已经到达交换地点,准备拿"+data2+"交换!");
data2 = exchanger.exchange(data2);//进行交换返回交换后的物品
System.out.println("线程"+Thread.currentThread().getName()+"交换成功,拿到"+data2);
} catch (Exception e) {
e.printStackTrace();
}
}
});
pool.shutdown();
}
}
注意:exchanger只能用于一对或者一组线程的交换。交换的线程不能为奇数,否则会出现死锁等待。
- 大小: 7.5 KB
分享到:
相关推荐
主要介绍了Java编程线程同步工具Exchanger的使用实例解析,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
Exchanger是java 5引入的并发类,Exchanger顾名思义就是用来做交换的。这里主要是两个线程之间交换持有的对象。当Exchanger在一个线程中调用exchange方法之后,会等待另外的线程调用同样的exchange方法。 两个线程都...
主要介绍了Java多线程编程之使用Exchanger数据交换实例,本文直接给出实例代码,需要的朋友可以参考下
java.util.concurrent包中的Exchanger类可用于两个线程之间交换信息。可简单地将Exchanger对象理解为一个包含两个格子的容器,通过exchanger方法可以向两个格子中填充信息。当两个格子中的均被填充时,该对象会自动...
Java 5.0里新加了4个协调线程间进程的同步装置,它们分别是Semaphore, CountDownLatch, CyclicBarrier和Exchanger,本例主要介绍Semaphore,Semaphore是用来管理一个资源池的工具,可以看成是个通行证
【2018最新最详细】并发多线程教程,课程结构如下 1.并发编程的优缺点 2.线程的状态转换以及基本操作 ...26.大白话说java并发工具类-Semaphore,Exchanger 27.一篇文章,让你彻底弄懂生产者--消费者问题
12反射 是java程序开发的特征之一,允许java程序对自身进行检查,并能直接操作程序的内部属性; instanceof操作符,instanceof.java; 获取类的信息,ViewClassInfoJrame.java; 动态调用类的方法,CallMetod.java; ...
主要介绍了Java多线程同步器代码详解,文章分别介绍了是CountDownLatch,Semaphore,Barrier和Exchanger以及其相关代码示例,具有一定参考价值,需要的朋友可以了解下。
18 线程——Exchanger 16. 19 线程——BlockingQueue 第17章 Java与XML 17. 1 用DOM处理XML文档 17. 2 用SAX处理XML文档 17. 3 用XSLT转换XML 17. 4 对象与XML的转换 第18章 Java Mail...
从Java字节码的角度看线程安全性问题.mp4 synchronized保证线程安全的原理(理论层面).mp4 synchronized保证线程安全的原理(jvm层面).mp4 单例问题与线程安全性深入解析.mp4 理解自旋锁,死锁与重入锁.mp4 深入...
Exchanger 这是一种两方栅栏,各方在栅栏位置上交换数据。 应用场景:当两方执行不对称的操作(读和取) 线程池 任务与执行策略之间的隐形耦合 线程饥饿死锁 运行时间较长的任务 ...
第13节从Java字节码的角度看线程安全性问题00:25:43分钟 | 第14节synchronized保证线程安全的原理(理论层面)00:13:59分钟 | 第15节synchronized保证线程安全的原理(jvm层面)00:25:03分钟 | 第16节单例问题与...
第13节从Java字节码的角度看线程安全性问题00:25:43分钟 | 第14节synchronized保证线程安全的原理(理论层面) 00:13:59分钟 | 第15节synchronized保证线程安全的原理(jvm层面)00:25:03分钟 | 第16节单例问题...
一、java.util.concurrent体系的主要大板块包含内容 二、Executors 三、Semaphor信号量 四、Exchanger线程交互 五、CyclicBarrier关卡模式 六、CountDownLatch计数器
java并发包讲解 可以找我要代码,qq 3341386488 ## 线程安全-并发容器JUC--原理以及分析 1.arrayList --copyonWriteArraylist 优缺点 2.HashSet,TreeSet -- CopyONWriteArraySet,ConcurrentSkipListSet 3....
JAVA并发编程-2-线程并发工具类一、Fork/Join1、分而治之与工作密取2、使用标准范式3、Fork/Join的同步用法4、Fork/Join的异步用法二、CountDownLatch三、CyclicBarrier四、Semaphore信号量五、Exchanger ...
第13节从Java字节码的角度看线程安全性问题00:25:43分钟 | 第14节synchronized保证线程安全的原理(理论层面) 00:13:59分钟 | 第15节synchronized保证线程安全的原理(jvm层面)00:25:03分钟 | 第16节单例问题...
第13节从Java字节码的角度看线程安全性问题00:25:43分钟 | 第14节sy nchronized保证线程安全的原理(理论层面)00:13:59分钟 | 第15节synchronized保证线程安全的原理(jvm层面)00:25:03分钟 | 第16节单例问题...