Exchanger 简介
JDK1.5 java.util.concurrent 包 提供了 Exchanger类允许在2个线程间定义同步点,当2个线程到达这个点,他们相互交换数据类型,使用第一个线程的数据类型变成第二个的,然后第二个线程的数据类型变成第一个的。
JDK 原文介绍如下:
A synchronization point at which threads can pair and swap elements within pairs. Each thread presents some object on entry to the exchange method, matches with a partner thread, and receives its partner's object on return. An Exchanger may be viewed as a bidirectional form of a SynchronousQueue. Exchangers may be useful in applications such as genetic algorithms and pipeline designs.
一个非常经典的并发问题:你有相同的数据buffer,一个或多个数据生产者,和一个或多个数据消费者。只是Exchange类只能同步2个线程,所以你只能在你的生产者和消费者问题中只有一个生产者和一个消费者时使用这个类。
Exchanger示例
这里用Exchanger来模拟经典的生产者和消费者问题,示例代码如下:
package com.ricky.java.test.exchanger;
import java.util.concurrent.Exchanger;
public class ExchangerTest {
/**
* @param args
*/
public static void main(String[] args) {
Exchanger<Data> exchanger = new Exchanger<>();
new Thread(new Producer(exchanger)).start();
new Thread(new Consumer(exchanger)).start();
}
//生产者
public static class Producer implements Runnable{
private Exchanger<Data> exchanger;
private int id = 1;
public Producer(Exchanger<Data> exchanger){
this.exchanger = exchanger;
}
@Override
public void run() {
boolean flag = true;
while(flag){
try {
Data data = new Data(id,"I produce data,id="+id,System.currentTimeMillis());
System.out.println("Producer start exchange,id="+id+" data="+data);
Data x = exchanger.exchange(data);
System.out.println("Producer exchange over "+id+" receive="+x);
id++;
sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//消费者
public static class Consumer implements Runnable{
private Exchanger<Data> exchanger;
private int id = 1;
public Consumer(Exchanger<Data> exchanger){
this.exchanger = exchanger;
}
@Override
public void run() {
boolean flag = true;
while(flag){
try {
Data data = new Data(id,"I have consume data,id="+id,System.currentTimeMillis());
System.out.println("Consumer start exchange,id="+id+" data="+data);
Data x = exchanger.exchange(data);
System.out.println("Consumer exchange over,id="+id+" receive="+x);
id++;
sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static class Data{
private int id;
private String content;
private long time;
public Data(){
}
public Data(int id,String content,long time){
this.id = id;
this.content = content;
this.time = time;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
@Override
public String toString() {
return "Data [id=" + id + ", content=" + content + ", time=" + time
+ "]";
}
}
public static void sleep(int millis) throws InterruptedException{
Thread.sleep(millis);
}
}