Exchanger
简介
Exchanger(交换者)是一个用于线程间协作的工具类。Exchanger用于进行线程间的数据交换。它提供一个同步点,在这个同步点两个线程可以交换彼此的数据。这两个线程通过exchange方法交换数据, 如果第一个线程先执行exchange方法,它会一直等待第二个线程也执行exchange,当两个线程都到达同步点时,这两个线程就可以交换数据,将本线程生产出来的数据传递给对方。因此使用Exchanger的重点是成对的线程使用exchange()方法,当有一对线程达到了同步点,就会进行交换数据。因此该工具类的线程对象是成对的。
Exchanger类提供了两个方法,String exchange(V x):用于交换,启动交换并等待另一个线程调用exchange;String exchange(V x,long timeout,TimeUnit unit):用于交换,启动交换并等待另一个线程调用exchange,并且设置最大等待时间,当等待时间超过timeout便停止等待。
总结:
- 交换的是数据的原生对象,可能存在线程安全问题
- 如果一个成对线程到达了交换点,其他线程未到达,会等待
- change方法总是成对的使用,不能出现更多的
案例1:exchange使用及延时
1、if the pair thread not reached change point,the thread will waiting.
2、use the change must be paired.
package com.ln.juc.utils.exchanger;
import java.util.concurrent.Exchanger;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* @ProjectName: java-concurrency
* @Package: com.ln.juc.utils.exchanger
* @Name:ExchangerExample1
* @Author:linianest
* @CreateTime:2021/1/17 11:18
* @version:1.0
* @Description TODO:
*/
public class ExchangerExample1 {
/**
* V r=exchange(V v)
* v: indicate the object the current thread wanted transfer
* r: indicate the other thread(pair) return object.
*
* <pre>
* NOTE:
* 1、if thepair thread not reached change point,the thread will waiting.
* 2、use the change must be paired.
* </pre>
*
* @param args
*/
public static void main(String[] args) {
Runtime.getRuntime().availableProcessors();
final Exchanger<String> exchanger = new Exchanger<>();
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " start.");
try {
// String result = exchanger.exchange("i am come from T-A", 10, TimeUnit.SECONDS);
String result = exchanger.exchange("i am come from T-A", 2, TimeUnit.SECONDS);
System.out.println(Thread.currentThread().getName() + " get value [" + result + "]");
} catch (InterruptedException | TimeoutException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " end.");
}, "==A==").start();
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " start.");
try {
TimeUnit.SECONDS.sleep(13);
String result = exchanger.exchange("i am come from T-B");
System.out.println(Thread.currentThread().getName() + " get value [" + result + "]");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " end.");
}, "==B==").start();
}
}
Exchanger 发送的是原生对象,不是拷贝对象
package com.ln.juc.utils.exchanger;
import java.util.concurrent.Exchanger;
/**
* @ProjectName: java-concurrency
* @Package: com.ln.juc.utils.exchanger
* @Name:ExchangerExample2
* @Author:linianest
* @CreateTime:2021/1/17 11:48
* @version:1.0
* @Description TODO: Exchanger 发送的是原生对象,不是拷贝对象
*/
public class ExchangerExample3 {
public static void main(String[] args) {
final Exchanger<Object> exchanger = new Exchanger<>();
new Thread(()->{
Object obj = new Object();
System.out.println("A will send the object "+obj);
try {
Object result = exchanger.exchange(obj);
System.out.println("A get the object "+result);
} catch (InterruptedException e) {
e.printStackTrace();
}
},"==A==").start();
new Thread(()->{
Object obj = new Object();
System.out.println("B will send the object "+obj);
try {
Object result = exchanger.exchange(obj);
System.out.println("B get the object "+result);
} catch (InterruptedException e) {
e.printStackTrace();
}
},"==B==").start();
}
}
案例2:循环调用
package com.ln.juc.utils.exchanger;
import com.ln.juc.atomic.AtomicInteger;
import java.util.concurrent.Exchanger;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
/**
* @ProjectName: java-concurrency
* @Package: com.ln.juc.utils.exchanger
* @Name:ExchangerExample2
* @Author:linianest
* @CreateTime:2021/1/17 11:48
* @version:1.0
* @Description TODO: Exchanger的重复循环调用
*/
public class ExchangerExample3 {
public static void main(String[] args) {
final Exchanger<Integer> exchanger = new Exchanger<>();
new Thread(() -> {
AtomicReference<Integer> value = new AtomicReference<Integer>(1);
try {
while (true) {
value.set(exchanger.exchange(value.get()));
System.out.println("A get the value " + value);
TimeUnit.SECONDS.sleep(3);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "==A==").start();
new Thread(() -> {
AtomicReference<Integer> value = new AtomicReference<Integer>(2);
try {
while (true) {
value.set(exchanger.exchange(value.get()));
System.out.println("B get the value " + value);
TimeUnit.SECONDS.sleep(2);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "==B==").start();
}
}