【搞定Java并发编程】第27篇:Java中的并发工具类之线程间交换数据的 Exchanger

上一篇:Java中的并发工具类之控制并发线程数的 Semaphore

Exchanger(交换者)是一个用于线程间协作的工具类。Exchanger用于进行线程间的数据交换。它提供一个同步点,在这个同步点,两个线程可以交换彼此的数据。这两个线程通过exchange方法交换数据,如果第一个线程先执行exchange()方法,它会一直等待第二个线程也执行exchange方法,当两个线程都到达同步点时,这两个线程就可以交换数据,将本线程生产出来的数据传递给对方。

下面来看下Exchange的应用场景:

1、Exchange可以用于移传算法。移传算法里需要选出两个人作为交配对象,这时候会交换两人的数据,并使用交叉规则得出2个交配结果;

2、Exchange用于校对工作。比如,我们需要将纸质银行流水通过人工的方式录入成电子银行流水,为了避免错误,采用AB岗两人进行录入,录入到Excel之后,系统需要加载这两个Excel,并对两个Excel数据进行校验,看是否录入一致。

【案例1】:

package com.zju.Exchanger;

import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestExchanger {

	private static final Exchanger<String>exgr = new Exchanger<String>();
	
	private static ExecutorService threadPool = Executors.newFixedThreadPool(2);
	
	public static void main(String[] args) {
		
		threadPool.execute(new Runnable(){
			@Override
			public void run() {
				try {
					String A = "银行流水A";    // A录入的银行流水数据
					exgr.exchange(A);
				} catch (Exception e) {
				}
			}
		});
		
		threadPool.execute(new Runnable(){
			@Override
			public void run() {
				try {
					String B = "银行流水B";    // B录入的银行流水数据
					String A = exgr.exchange("B");
					System.out.println("A录入的是:" + A);
					System.out.println("B录入的是:" + B);
					System.out.println("A和B录入的数据是否一致:" + A.equals(B));
				} catch (Exception e) {
				}
			}
		});
	}
}

运行结果:

在Exchanger中,如果一个线程已经到达了exchanger节点时,对于它的伙伴节点的情况有三种:

  1. 如果它的伙伴节点在该线程到达之前已经调用了exchanger方法,则它会唤醒它的伙伴然后进行数据交换,得到各自数据返回;
  2. 如果它的伙伴节点还没有到达交换点,则该线程将会被挂起,等待它的伙伴节点到达被唤醒,完成数据交换;
  3. 如果当前线程被中断了则抛出异常,或者等待超时了,则抛出超时异常。

下面就来看看Exchanger的源码:

Exchanger算法的核心是通过一个可交换数据的slot,以及一个可以带有数据item的参与者。

Exchanger 有单槽位和多槽位之分,单个槽位在同一时刻只能用于两个线程交换数据,这样在竞争比较激烈的时候,会影响到性能,多个槽位就是多个线程可以同时进行两个的数据交换,彼此之间不受影响,这样可以很好的提高吞吐量。 

具体源码分析参考:Java 并发 --- Exchanger源码分析


上一篇:Java中的并发工具类之控制并发线程数的 Semaphore

猜你喜欢

转载自blog.csdn.net/pcwl1206/article/details/85068462