我有一个非常简单的问题,我试图在两个任务: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中的行,我会看到生成的数字仍然存在。那为什么不交换对象?
答案 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);
。