Exchanger(交换者)

Exchanger是一个线程间提供数据交换功能的写作工具,他提供了一个同步点,在这个同步点,两个线程可以交换彼此的数据。线程间通过调用excahange()方法交换数据,如果第一个线程先到达同步点,执行exchange方法,那么他会一直在同步点等待第二个线程到达同步点,第二个线程也执行exchange方法,这时两个线程都到达同步点,可以交换彼此的数据。

使用:

(1)创建一个Exchanger对象;

(2)在要交换(同步)数据的同步点调用excr.exchange( )方法

public class ExchangerTest {
    static Exchanger<String> exc = new Exchanger<>();  //创建一个Exchanger对象;
    public static void main(String[] args) throws InterruptedException {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    String A= "银行流水A";
                  //在要交换(同步)数据的同步点调用excr.exchange()方法
                    String B = exc.exchange(A); 
                    System.out.println("A的视角: A、B流水是否一致:" + A.equals(B) + "   A录入的是:" + A + "   B录入的是:" + B);

                }
                catch(Exception e){
                    e.printStackTrace();
                }

            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    String B= "银行流水B";
                    //在要交换(同步)数据的同步点调用excr.exchange()方法
                    String A = exc.exchange(B); 
                    System.out.println("B的视角: A、B流水是否一致:" + A.equals(B) + "   A录入的是:" + A + "   B录入的是:" + B);
                }
                catch(Exception e){
                    e.printStackTrace();
                }

            }
        }).start();

    }
}

输出结果:

A的视角: A、B流水是否一致:false   A录入的是:银行流水A   B录入的是:银行流水B
B的视角: A、B流水是否一致:false   A录入的是:银行流水A   B录入的是:银行流水B

可以看出,Exchanger的“交换”更偏向于数据的同步与共享,而不是“你的给我,我的给你”这样有来有回的交换,是“你知道一个信息,我知道另一个消息,我们彼此交换了信息,那么我们就都知道了两个消息”。如果不愿意在同步点一直等待另一个线程,那么可以用设置等待时间的exchange方法:excr.exchange(V x, long timeout, timeUnit unit)。

*注意:

Exchanger交换数据是成对的交换;

Exchanger可以看做双向的同步队列,一个线程从个队列头部进行操作,一个从个队列尾部进行操作;

使用场景:
需要数据交换共享的场景,例如遗传算法中,需要选择两个人来交配,交换两人的数据并根据交换规则来得到交配结果,再例如用于校对工作,交换两个线程的数据,用于校对两个线程的数据是否相等;