本实例使用Exchanger来演示一对一的生产者和消费者问题
.并发任务间的数据交换(生产者—消费模型(一对一))
本案例使用Exchanger同步辅助类实现,该类运行在并发任务之间交换数据。该类允许两个线程之间定义同步点,当两个线程都到达同步点的时候,它们交换数据结构,因此第一个线程
的数据结构进入到第二个线程中,同事第二个线程的数据结构进入到第一个线程中。
1.Consumer类
/**
*
* @author fcs
* @date 2015-5-2
* 描述:并发任务间的数据交换
* 说明:使用同步辅助工具Exchanger
*/
public class Consumer implements Runnable{
private List<String> buffer;
private final Exchanger<List<String>> exchanger;
public Consumer(List<String> buffer, Exchanger<List<String>> exchanger) {
super();
this.buffer = buffer;
this.exchanger = exchanger;
}
@Override
public void run() {
int cycle = 0;
for(int i =0;i< 10;i++){
System.out.printf("Consumer: Cycle %d\n",cycle);
//这里消费者要消费数据,就要先获得数据,调用exchange方法交换数据结构
try {
buffer = exchanger.exchange(buffer);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Consumer size: "+buffer.size());
//将生产者放入消费者buffer列表中的10个字符串打印到控制台,并从列表中删除,保持一个空列表
for(int j =0 ;j < 10;j++){
String message = buffer.get(0);
System.out.println("Consumer: "+message);
buffer.remove(0);
}
cycle++;
}
}
}
2.Producer类
public class Producer implements Runnable{
private List<String> buffer; //生产者和消费者用于交换的数据结构
private final Exchanger<List<String>> exchanger; //同步生产者和消费者的交换对象
public Producer(List<String> buffer, Exchanger<List<String>> exchanger) {
super();
this.buffer = buffer;
this.exchanger = exchanger;
}
@Override
public void run() {
int cycle = 1;
for(int i =0;i< 10;i++){
System.out.printf("Produceer: Cycle %d\n",cycle);
for(int j =0 ;j < 10;j++){
String message = "Event" +((i * 10)+j);
System.out.printf("Producer :%s\n",message);
buffer.add(message);
}
try{
buffer = exchanger.exchange(buffer); //该方法会抛出异常
}catch(Exception e){
e.printStackTrace();
}
System.out.println("Producer: "+buffer.size());
}
}
}
3.测试类
/**
*
* @author fcs
* @date 2015-5-2
* 描述:生产者---消费者(一对一)问题,使用同步辅助工具实现
* 说明:
*/
public class Main {
public static void main(String[] args) {
List<String> buffer1 = new ArrayList<String>();
List<String> buffer2 = new ArrayList<String>();
//创建exchanger对象,用来同步生产者和消费者
Exchanger<List<String>> exchanger = new Exchanger<List<String>>();
Producer producer = new Producer(buffer1,exchanger);
Consumer consumer = new Consumer(buffer2,exchanger);
Thread pthread = new Thread(producer);
Thread cthread = new Thread(consumer);
pthread.start();
cthread.start();
}
}
演示效果:
5.Exchanger: 提供了两个线程之间的数据交换的同步机制。而其他的同步机制,则需要根据各自的上述特性来对其选择使用。我们需要根据应用程序的特性来选择合适的同步机制。
该类的主要方法:
exchange(): 等待另一个线程到达此交换点(除非当前线程被中断),然后将给定的对象传送给该线程,并接收该线程的对象。
exchange(V data,long time,TimeUnit unit):第一个传入参数的类型是V,即要交换的数据结构,这个方法被调用后,线程将休眠直到被中断,或者其他线程到达,或者已经耗费了指定的time值。
内存一致性效果:对于通过 Exchanger 成功交换对象的每对线程,每个线程中在 exchange() 之前的操作 happen-before 从另一线程中相应的 exchange() 返回的后续操作。