Exchanger主要用于成对线程交换数据,不成对的话当前线程就会阻塞。
1.构造方法
public Exchanger();
2.核心方法
public V exchange(V x);
public V exchange(V x, long timeout, TimeUnit unit);
3.测试代码
public V exchange(V x)方法测试
定义了两个线程,线程a和线程b,线程a发送数据 data - a,线程b发送数据 data - b。
public class MyDemo {
private final static Exchanger<String> EXCHANGER = new Exchanger<>();
public static void main(String[] args){
new Thread(()->{
String res = null;
try {
res = EXCHANGER.exchange("data - A");
System.out.println(Thread.currentThread().getName() + "获得数据"+res);
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
new Thread(()->{
String res = null;
try {
res = EXCHANGER.exchange("data - B");
System.out.println(Thread.currentThread().getName() + "获得数据"+res);
} catch (InterruptedException e) {
e.printStackTrace();
}
},"B").start();
}
}
public V exchange(V x, long timeout, TimeUnit unit)方法测试
如下代码所示:此方法在阻塞一段时间拿不到数据就不等待了,直接抛出TimeoutException
public class MyDemo {
private final static Exchanger<String> EXCHANGER = new Exchanger<>();
public static void main(String[] args){
new Thread(()->{
String res = null;
try {
res = EXCHANGER.exchange("data - A",2, TimeUnit.SECONDS);
System.out.println(Thread.currentThread().getName() + "获得数据"+res);
} catch (InterruptedException | TimeoutException e) {
System.out.println("我超时了");
}
},"A").start();
}
}
4.注意点
- 如果当前的exchanger的线程并未成对出现,那么就会产生阻塞,而且是一致阻塞,等待别人发消息
- Exchanger发送的如果是对象,且几个线程拿到的是同一个对象,会发生线程的安全问题,所以在实际中药解决线程的安全问题。
- Exchanger是可以循环使用的
测试Exchanger发送的对象和别人接受的是同一个对象
public static void main(String[] args) {
Exchanger<Object> exchanger = new Exchanger<>();
new Thread(()->{
Object obj = new Object();
Object o = null;
try {
System.out.println(Thread.currentThread().getName() + "发送的数据"+obj.hashCode());
o = exchanger.exchange(obj);
System.out.println(Thread.currentThread().getName()+"从其他线程接收到的"+o.hashCode());
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
new Thread(()->{
Object obj = new Object();
Object o = null;
try {
System.out.println(Thread.currentThread().getName() + "发送的数据"+obj.hashCode());
o = exchanger.exchange(obj);
System.out.println(Thread.currentThread().getName()+"从其他线程接收到的"+o.hashCode());
} catch (InterruptedException e) {
e.printStackTrace();
}
},"B").start();
}
测试Exchanger是可以循环使用的
public static void main(String[] args) {
Exchanger<Integer> exchanger = new Exchanger<>();
new Thread(()->{
try {
while(true){
System.out.println(Thread.currentThread().getName()+"发送数据--"+1);
Integer res = exchanger.exchange(1);
System.out.println(Thread.currentThread().getName()+"接受数据--"+res);
TimeUnit.SECONDS.sleep(3);
}
}catch (InterruptedException e){
e.printStackTrace();
}
},"A").start();
new Thread(()->{
try {
while(true){
System.out.println(Thread.currentThread().getName()+"发送数据--"+2);
Integer res = exchanger.exchange(2);
System.out.println(Thread.currentThread().getName()+"接受数据--"+res);
TimeUnit.SECONDS.sleep(2);
}
}catch (InterruptedException e){
e.printStackTrace();
}
},"B").start();
}