2

我有一个非常简单的问题,我尝试在两个任务之间交换一个对象(在这种情况下是一个 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 中的行,我会看到生成的数字仍然存在。那么为什么它不交换对象呢?

4

2 回答 2

4

交换器不会就地交换引用,而是返回交换的对象。所以你应该写这样的东西:

List<Integer> received = exchanger.exchange(ints);
System.out.println("Consumer:");
for(Integer x : received) {
    System.out.print(" " + x);
        ...
}

顺便说一句,我认为交换器不适合生产者/消费者......

于 2011-08-14T15:03:00.437 回答
0

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

于 2011-08-14T15:15:07.787 回答