Java高并发编程中Exchanger的使用及详细介绍-刘宇
作者:刘宇
优快云博客地址:https://blog.youkuaiyun.com/liuyu973971883
有部分资料参考,如有侵权,请联系删除。如有不正确的地方,烦请指正,谢谢。
一、什么是Exchanger
主要用于一对线程之间交换信息,必须是给成对的线程使用。当线程A执行exchange方法时,则会等待线程B执行exchange方法,实现两个线程的想换转换信息。如果这两个线程之间有一个没有执行exchange方法,那么另一个将会被阻塞住,即两个线程必须都到达交换点。
二、Exchanger的基本使用
1、构造函数
- 需要指定一个泛型,这里的泛型是指传递数据的类型。
Exchanger<V> exchanger = new Exchanger<V>();
2、exchange方法
- x:需要传递的信息
- 返回值:对方传递过来的信息
public V exchange(V x)
3、exchange方法
- x:需要传递的信息
- timeout:超时时间,如果在这时间内,另一个线程还未执行exchange,则抛出timeout异常
- unit:时间单位
- 返回值:对方传递过来的信息
注:当线程A出现了timeout时,则线程B在执行exchange时将会得不到回应,那线程B将会一直等待下去。
public V exchange(V x, long timeout, TimeUnit unit)
三、简单示例
1、exchange()
package com.brycen.concurrency03.exchanger;
import java.util.concurrent.Exchanger;
public class ExchangerExample1 {
public static void main(String[] args) {
final Exchanger<String> exchanger = new Exchanger<String>();
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("Thread A start");
String result = exchanger.exchange("I am from A");
System.out.println(Thread.currentThread().getName()+" get result:["+result+"]");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread A end");
}
},"==A==").start();
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("Thread B start");
String result = exchanger.exchange("I am from B");
System.out.println(Thread.currentThread().getName()+" get result:["+result+"]");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread B end");
}
},"==B==").start();
}
}
输出结果:
- 程序正常结束
Thread A start
Thread B start
==A== get result:[I am from B]
Thread A end
==B== get result:[I am from A]
Thread B end
2、exchange(V x, long timeout, TimeUnit unit)
package com.brycen.concurrency03.exchanger;
import java.util.concurrent.Exchanger;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class ExchangerExample1 {
public static void main(String[] args) {
final Exchanger<String> exchanger = new Exchanger<String>();
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("Thread A start");
//向线程B发送信息,超时时间为5秒
String result = exchanger.exchange("I am from A",5,TimeUnit.SECONDS);
System.out.println(Thread.currentThread().getName()+" get result:["+result+"]");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
System.out.println("time out");
}
System.out.println("Thread A end");
}
},"==A==").start();
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("Thread B start");
//休眠10,让线程A出现超时异常
TimeUnit.SECONDS.sleep(10);
String result = exchanger.exchange("I am from B");
System.out.println(Thread.currentThread().getName()+" get result:["+result+"]");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread B end");
}
},"==B==").start();
}
}
输出结果:
- 程序无法结束,因为线程B还处于等待状态。
Thread A start
Thread B start
java.util.concurrent.TimeoutException
at java.util.concurrent.Exchanger.exchange(Exchanger.java:626)
at com.brycen.concurrency03.exchanger.ExchangerExample1$1.run(ExchangerExample1.java:15)
at java.lang.Thread.run(Thread.java:745)
time out
Thread A end
3、exchange传递对象时,传递的是否是引用
package com.brycen.concurrency03.exchanger;
import java.util.concurrent.Exchanger;
public class ExchangerExample2 {
public static void main(String[] args) {
final Exchanger<Object> exchanger = new Exchanger<Object>();
new Thread(new Runnable() {
@Override
public void run() {
try {
Object aObj = new Object();
System.out.println("A will send the object "+aObj);
Object result = exchanger.exchange(aObj);
System.out.println(Thread.currentThread().getName()+" get result:["+result+"]");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread A end");
}
},"==A==").start();
new Thread(new Runnable() {
@Override
public void run() {
try {
Object bObj = new Object();
System.out.println("B will send the object "+bObj);
Object result = exchanger.exchange(bObj);
System.out.println(Thread.currentThread().getName()+" get result:["+result+"]");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread B end");
}
},"==B==").start();
}
}
输出结果:
- 从结果可以看出,exchange传递的对象是引用传递,即是同一个对象。那么值得注意的是,当这两个线程操作这个对象的时候就会出现线程安全问题。
A will send the object java.lang.Object@67437b8f
B will send the object java.lang.Object@28c5e3c5
==B== get result:[java.lang.Object@67437b8f]
Thread B end
==A== get result:[java.lang.Object@28c5e3c5]
Thread A end