Exchanger 类表示一种会合点,两个线程可以在这里交换对象。两个线程各自调用 exchange 方法进行交换,当线程 A 调用 Exchange 对象的 exchange 方法后,它会陷入阻塞状态,直到线程B也调用了 exchange 方法,然后以线程安全的方式交换数据,之后线程A和B继续运行。
exchange 方法有两个重载实现,在交换数据的时候还可以设置超时时间。如果一个线程在超时时间内没有其他线程与之交换数据,就会抛出 TimeoutException 超时异常。如果没有设置超时时间,则会一直等待。
//交换数据,并设置超时时间
public V exchange(V x, long timeout, TimeUnit unit)
throws InterruptedException, TimeoutException
//交换数据
public V exchange(V x) throws InterruptedException
如下的示例演示了 Exchanger 的使用方法。交换数据的类型是 String 字符串,两个线程的创建时间相差 5s,exchange 的超时时间是 100s,线程启动后打印初始字符串和交换后的字符串。
public class ExchangerTest {
private Exchanger<String> exchanger = new Exchanger<>();
public void test() throws Exception{
testRunner("hello");
Thread.sleep(5000);
testRunner("world");
}
private void println(String msg){
SimpleDateFormat sdf = new SimpleDateFormat("[YYYY-MM-dd HH:mm:ss:SSS] ");
System.out.println(sdf.format(new Date()) + msg);
}
public void testRunner(String data){
new Thread(() -> {
try {
println(Thread.currentThread().getName() + " receive " +data);
// String newData = exchanger.exchange(data);
String newData = exchanger.exchange(data,100,TimeUnit.SECONDS);
println(Thread.currentThread().getName() + " has " +newData);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}).start();
}
}
执行结果如下,Thread-0 初始字符串为 hello,Thread-1 初始字符串为 world,Thread-0 等待交换数据等待了 5s,交换数据后 Thread-0 持有的字符串为 world,Thread-1 持有的字符串为 hello。
[2017-08-20 14:53:18:021] Thread-0 receive hello
[2017-08-20 14:53:23:003] Thread-1 receive world
[2017-08-20 14:53:23:003] Thread-1 has hello
[2017-08-20 14:53:23:003] Thread-0 has world
分享学习笔记和技术总结,内容涉及 Java 进阶、虚拟机、MySQL、NoSQL、分布式计算、开源框架等多个领域,欢迎关注作者。

网友评论