Обменник не обменивается () - PullRequest
2 голосов
/ 14 августа 2011

У меня довольно простая проблема, в которой я пытаюсь обменять объект (в данном случае массив int) между двумя задачами: Producer и Consumer.Класс Producer создает массив int и затем пытается обменять его с массивом Consumer (который является пустым массивом) с использованием объекта Exchanger.Но кажется, что это не работает: когда Потребитель пытается напечатать массив, он ничего не получает.

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 ]

4 голосов
/ 14 августа 2011

Обменник не меняет ссылки на месте, а возвращает обмениваемый объект.Поэтому вы должны написать что-то вроде:

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

Кстати, я не думаю, что обменники подходят для производителя / потребителей ...

0 голосов
/ 14 августа 2011

Обмен не магический; объект Exchanger не может заменить ссылки на сам объект. Документация говорит нам, что вызов функции возвращает объект, который был предоставлен другим потоком, как только точка обмена достигнута, как мы ее «получаем». На самом деле я ничего этого не делал, но я предполагаю, что вы должны вернуть этот результат обратно; то есть ints = exchanger.exchange(ints); в обоих классах.

...