并发编程-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

posted @ 2018-12-20 21:47  qjm201000  阅读(256)  评论(0编辑  收藏  举报