抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

java并发工具类-Exchanger

Exchanger 简介

​ Exchange位于JUC包下面,主要是用于线程之间数据交换的工具类,经常用于管道设计和遗传算法中,Exchanger用于进行线程间的数据交换,它提供一个同步点,在这个同步点,两个线程可以交换彼此的数据。这两个线程通过exchange 方法交换数据,如果第一个线程先执行exchange 方法,它会一直等待第二个线程也执行exchange 方法,当两个线程都到达同步点时,这两个线程就可以交换数据。

可以将Exchange看做是一个双向数据传输的SynchronousQueue。

  • 此类提供对外的操作是同步的;
  • 用于成对出现的线程之间交换数据;
  • 可以视作双向的同步队列;
  • 可应用于基因算法、流水线设计等场景。

Exchanger 提供的方法

构造方法

1
2
3
4
5
6
/**
* Creates a new Exchanger.
*/
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();
//线程1 拿着零食来交换
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);

});

//线程2 拿着钱来交换
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换回的数据为 钱

评论