交换器似乎没有交换()

时间:2011-08-14 14:48:41

标签: java multithreading concurrency jsr166

我有一个非常简单的问题,我试图在两个任务:Producer和Consumer之间交换一个对象(在本例中是一个int数组)。 Producer类生成一个int数组,并尝试使用Exchanger对象与Consumer数组(它是一个空数组)交换它。但似乎它不起作用:当消费者试图打印数组时,它什么都没有。

public class Producer implements Runnable{
private Exchanger<List<Integer>> exchanger;
private List<Integer> ints = new ArrayList<Integer>();

public Producer(Exchanger<List<Integer>> ex) {
    this.exchanger = ex;
}

public void run() {
    RandomGenerator.Integer gen = new RandomGenerator.Integer();
    try{
    while(!Thread.interrupted()) {
        for (int i = 0;i < Test.LIST_SIZE;i++) 
            ints.add(gen.next());
        exchanger.exchange(ints);
        //for(Integer x : ints) 
            //System.out.print(" " + x);
        //System.out.println();
    }
    }catch(InterruptedException e) {
        System.out.println("Producer interrupted");
    }
}
}


public class Consumer implements Runnable {
private Exchanger<List<Integer>> exchanger;
private List<Integer> ints = new ArrayList<Integer>();

public Consumer(Exchanger<List<Integer>> ex) {
    this.exchanger = ex;
}

public void run() {
    try{
    while(!Thread.interrupted()) {
        exchanger.exchange(ints);
        System.out.println("Consumer:");
        for(Integer x : ints) {
            System.out.print(" " + x);
            ints.remove(x);
        }
        System.out.println();
    }
    } catch(InterruptedException e) {
        System.out.println("Consumer interrupted");
    }
}
}


public class Test {
public static final int LIST_SIZE = 10;

public static void main(String[] args) throws InterruptedException {
    ExecutorService exec = Executors.newCachedThreadPool();
    Exchanger<List<Integer>> exchanger = new Exchanger<List<Integer>>();
    exec.execute(new Producer(exchanger));
    exec.execute(new Consumer(exchanger));
    TimeUnit.MILLISECONDS.sleep(5);
    exec.shutdownNow();
}

如果我取消注释Producer中的行,我会看到生成的数字仍然存在。那为什么不交换对象?

2 个答案:

答案 0 :(得分:4)

交换器不会交换引用,但返回交换的对象。所以你应该写一些类似的东西:

List<Integer> received = exchanger.exchange(ints);
System.out.println("Consumer:");
for(Integer x : received) {
    System.out.print(" " + x);
        ...
}
顺便说一句,我不认为交换者适合生产者/消费者......

答案 1 :(得分:0)

交换并不神奇; Exchanger对象不能替换对象引用本身。文档告诉我们,一旦达到交换点,调用该函数将返回另一个线程提供的对象,这就是我们“接收”它的方式。我实际上没有做过这些,但我认为你的意思是将这个结果分配回来;即两个班级中的ints = exchanger.exchange(ints);