java并发工具类-Exchanger

Exchanger 简介
Exchange位于JUC包下面,主要是用于线程之间数据交换的工具类,经常用于管道设计和遗传算法中,Exchanger用于进行线程间的数据交换,它提供一个同步点,在这个同步点,两个线程可以交换彼此的数据。这两个线程通过exchange 方法交换数据,如果第一个线程先执行exchange 方法,它会一直等待第二个线程也执行exchange 方法,当两个线程都到达同步点时,这两个线程就可以交换数据。
可以将Exchange看做是一个双向数据传输的SynchronousQueue。
- 此类提供对外的操作是同步的;
- 用于成对出现的线程之间交换数据;
- 可以视作双向的同步队列;
- 可应用于基因算法、流水线设计等场景。
Exchanger 提供的方法
构造方法
1 2 3 4 5 6
|
public Exchanger() { participant = new Participant(); }
|
创建一个新的Exchange。
主要方法
这个类提供对外的接口非常简洁,一个无参构造函数,两个重载的范型exchange方法:
等待另外一个线程到达此交换点(除非当前线程被中断),将给定的对象x传送给该线程,并且接收该线程的对象。
1
| public V exchange(V x) throws InterruptedException
|
等待另外一个线程到达此交换点(除非当前线程被中断,或者超出了指定的等待时间),将指定的对象x传送给该线程,同时接收该线程的对象。
1 2
| public V exchange(V x, long timeout, TimeUnit unit) throws InterruptedException, TimeoutException
|
Exchanger的应用场景
Exchanger可以用于遗传算法,遗传算法里需要选出两个人作为交配对象,这时候会交换两人的数据,并使用交叉规则得出2个交配结果。
只要用于两个线程之间交换数据。
如果两个线程有一个没有到达exchange方法,则会一直等待,如果担心有特殊情况发生,避免一直等待,可以使用exchange(V x, long timeout, TimeUnit unit)设置最大等待时长。
案例
比如生活中两个人,一个人有零食,另一个人有钱,他们两个想等价交换,对好口号在某个地方相见,一个人先到了之后,必须等另一个人带着需要的东西来了之后,才能开始交换。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| public class ExchangerTest {
public static void main(String[] args) { Exchanger exchanger = new Exchanger(); ExecutorService service = Executors.newCachedThreadPool(); service.submit(() -> { String data1 = "零食"; System.out.println("线程" + Thread.currentThread().getName() + "正在把数据 " + data1 + " 换出去"); String data2 = null; try { System.out.println("正在交换等待10s"); Thread.sleep((long) Math.random() * 10000); data2 = (String) exchanger.exchange(data1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程 " + Thread.currentThread().getName() + "换回的数据为 " + data2);
});
service.submit(() -> { String data1 = "钱"; System.out.println("线程" + Thread.currentThread().getName() + "正在把数据 " + data1 + " 交换出去"); String data2 = null; try { System.out.println("正在交换等待10s"); Thread.sleep((long) (Math.random() * 10000)); data2 = (String) exchanger.exchange(data1); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println("线程 " + Thread.currentThread().getName() + "交换回来的数据是: " + data2);
});
service.shutdown();
} }
|
输出
1 2 3 4 5 6
| 线程pool-1-thread-1正在把数据 零食 换出去 正在交换等待10s 线程pool-1-thread-2正在把数据 钱 交换出去 正在交换等待10s 线程 pool-1-thread-2交换回来的数据是: 零食 线程 pool-1-thread-1换回的数据为 钱
|