BlockingQueue: put () и isEmpty () не работают вместе? - PullRequest
0 голосов
/ 22 января 2009

Я хотел бы иметь SynchronousQueue, где я вставляю элементы из одного потока с помощью put(), поэтому ввод блокируется, пока элемент не будет взят в другой поток.

В другом потоке я выполняю много вычислений и время от времени хочу проверить, доступен ли уже элемент, и использовать его. Но кажется, что isEmpty() всегда возвращает true, даже если другой поток ожидает при вызове put().

Как, черт возьми, это возможно? Вот пример кода:

@Test
public void testQueue() throws InterruptedException {
    final BlockingQueue<Integer> queue = new SynchronousQueue<Integer>();

    Thread t = new Thread(new Runnable() {
        @Override
        public void run() {
            while (true) {
                if (!queue.isEmpty()) {
                    try {
                        queue.take();
                        System.out.println("taken!");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                // do useful computations here (busy wait)
            }
        }
    });
    t.start();

    queue.put(1234);
    // this point is never reached!
    System.out.println("hello");
}

РЕДАКТИРОВАТЬ: Ни isEmpty (), ни peek () не работают, нужно использовать poll (). Спасибо!

Ответы [ 3 ]

6 голосов
/ 22 января 2009

С http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/SynchronousQueue.html#put(E):

IsEmpty
public boolean isEmpty ()
Всегда возвращает истину. SynchronousQueue не имеет внутренней емкости.

(не рассматривал это в мельчайших подробностях, но вы могли бы взглянуть на poll или вместо )

1 голос
/ 22 января 2009

ваш код выглядит так, как будто вы пытаетесь сделать опрос. почему бы просто не вызвать метод poll ()?

1 голос
/ 22 января 2009

В дополнение к ответу Тима - вы ничего не делаете в потоке потребителя, но постоянно вызываете isEmpty () в узком цикле. Вместо того, чтобы просить ОС не запускать ее до тех пор, пока для нее не появится что-то полезное, потребительский поток постоянно занят. Даже если isEmpty работал правильно, поток производителя редко получал шанс на запуск.

Вы могли бы (если isEmpty () сработал, или вы переключились на использование poll ()) заставить потребителя немного поспать между тестами, когда очередь пуста, чтобы дать возможность производителю запустить, или (предпочтительно) просто возьмите тест isEmpty () и разрешите потоку блокировать мьютекс внутри take () разумным способом вместо опроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...