Вопрос

Я хотел бы иметь 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().Спасибо!

Это было полезно?

Решение

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top