Exchanger
- Exchanger是两个任务之间交换对象的栅栏。当这些任务进入栅栏时,各自拥有一个对象,当它们离开时,它们都拥有之前由对象持有的对象。
- Exchanger的典型应用场景是:一个任务在创建对象,这些对象的生产代价很高昂,而另一个任务在消费这些对象。通过这种方式,可以有更多的对象在被创建的同时被消费。
package com21concurrent;
import com15.BasicGenerator;
import com15.Generator;
import java.util.List;
import java.util.concurrent.*;
/**
* Created by Panda on 2018/6/2.
*/
class ExchangerProducer<T> implements Runnable{
private Generator<T> generator;
private Exchanger<List<T>> exchanger;
private List<T> holder;
public ExchangerProducer(Generator<T> generator, Exchanger<List<T>> exchanger, List<T> holder) {
this.generator = generator;
this.exchanger = exchanger;
this.holder = holder;
}
@Override
public void run() {
try{
while (!Thread.interrupted()){
for (int i = 0; i <ExchangerDemo.size ; i++) {
holder.add(generator.next());
holder=exchanger.exchange(holder);
}
}
}catch (InterruptedException e){
}
}
}
class ExchangeConsumer<T> implements Runnable{
private Exchanger<List<T>> exchanger;
private List<T> holder;
private volatile T value;
public ExchangeConsumer(Exchanger<List<T>> exchanger, List<T> holder) {
this.exchanger = exchanger;
this.holder = holder;
}
@Override
public void run() {
try{
while (!Thread.interrupted()){
holder=exchanger.exchange(holder);
for(T x:holder){
value=x;
holder.remove(x);
}
}
}catch (InterruptedException e){
}
System.out.println("Final value: "+value);
}
}
public class ExchangerDemo {
static int size=10;
static int delay=5;
public static void main(String[] args) throws Exception{
if(args.length>0) size=new Integer(args[0]);
if(args.length>1) delay=new Integer(args[1]);
ExecutorService executorService = Executors.newCachedThreadPool();
Exchanger<List<Fat>> listExchanger=new Exchanger<>();
List<Fat> producerList=new CopyOnWriteArrayList<>();
List<Fat> consumerList=new CopyOnWriteArrayList<>();
executorService.execute(new ExchangerProducer<>(BasicGenerator.create(Fat.class),listExchanger ,producerList));
executorService.execute(new ExchangeConsumer<>(listExchanger,consumerList));
TimeUnit.SECONDS.sleep(delay);
executorService.shutdownNow();
}
}