并发编程-concurrent指南-交换机Exchanger
java.util.concurrent包中的Exchanger类可用于两个线程之间交换信息。可简单地将Exchanger对象理解为一个包含两个格子的容器,通过exchanger方法可以向两个格子中填充信息。当两个格子中的均被填充时,该对象会自动将两个格子的信息交换,然后返回给线程,从而实现两个线程的信息交换。
另外需要注意的是,Exchanger类仅可用作两个线程的信息交换,当超过两个线程调用同一个exchanger对象时,得到的结果是随机的,exchanger对象仅关心其包含的两个“格子”是否已被填充数据,当两个格子都填充数据完成时,该对象就认为线程之间已经配对成功,然后开始执行数据交换操作。
Exchanger可以在两个线程之间交换数据,只能是2个线程,他不支持更多的线程之间互换数据。
Exchanger是在两个任务之间交换对象的栅栏,当这些任务进入栅栏时,它们各自拥有一个对象。当他们离开时,它们都拥有之前由对象持有的对象。
它典型的应用场景是:一个任务在创建对象,这些对象的生产代价很高昂,而另一个任务在消费这些对象。通过这种方式,可以有更多的对象在被创建的同时被消费。
public class ExchangerRunnable implements Runnable{ private Exchanger<String> exchanger; private String data; private int random; public ExchangerRunnable(Exchanger exchanger,String data,int random){ this.exchanger = exchanger; this.data = data; this.random = random; } @Override public void run() { System.out.println(Thread.currentThread().getName()+",数据:"+data); try { TimeUnit.SECONDS.sleep(random); String data_new = exchanger.exchange(data); System.out.println(Thread.currentThread().getName()+",数据:"+data_new); } catch (InterruptedException e) { e.printStackTrace(); } } }
public class Main { public static void main(String[] args) { //交换机 Exchanger exchanger = new Exchanger(); ExchangerRunnable exchangerRunnable = new ExchangerRunnable(exchanger,"aa",3); ExchangerRunnable exchangerRunnable1 = new ExchangerRunnable(exchanger,"bb",10); new Thread(exchangerRunnable).start(); new Thread(exchangerRunnable1).start(); } }
结果:
Thread-0,数据:aa Thread-1,数据:bb Thread-0,数据:bb Thread-1,数据:aa
注意:
1.当线程A调用Exchange对象的exchange()方法后,他会陷入阻塞状态,直到线程B也调用了exchange()方法,然后以线程安全的方式交换数据,之后线程A和B继续运行。
2.多个线程时,有且只有两个线程进入数据交换。
源码地址:https://github.com/qjm201000/concurrent_exchanger.git