BlockingQueue: put () и isEmpty () не работают вместе?

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

В другом потоке я выполняю множество вычислений и время от времени хочу проверять, доступен ли уже элемент, и использовать его. Но кажется, что isEmpty() всегда возвращает истину, даже если другой поток ожидает вызова 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 (). Спасибо!

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
1 770
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

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

пустой
публичное логическое значение isEmpty ()
Всегда возвращает истину. SynchronousQueue не имеет внутренней емкости.

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

Боже мой, я должен был прочитать javadoc ... Я пробовал и peek (), и isEmpty (), и оба всегда возвращают null или true.

martinus 22.01.2009 17:35

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

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

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

Другие вопросы по теме