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




От http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/SynchronousQueue.html#put(E):
пустой
публичное логическое значение isEmpty ()
Всегда возвращает истину. SynchronousQueue не имеет внутренней емкости.
(не рассматривал это подробно, но вы можете вместо этого взглянуть на голосование или брать)
В дополнение к ответу Тима - вы ничего не делаете в потоке потребителя, а постоянно вызываете isEmpty () в замкнутом цикле. Вместо того, чтобы просить ОС не запускать его до тех пор, пока для него не появится что-то полезное, потребительский поток постоянно занят. Даже если isEmpty работал правильно, поток производителя редко получал возможность работать.
Вы можете (если isEmpty () действительно сработали или вы переключились на использование poll ()) заставить потребителя ненадолго засыпать между тестами, когда очередь пуста, чтобы дать производителю возможность запустить, или (желательно) просто вынуть isEmpty () проверяет и позволяет потоку блокировать мьютекс внутри take () разумным образом вместо опроса.
ваш код выглядит так, как будто вы пытаетесь провести опрос. почему бы просто не вызвать метод poll ()?
Боже мой, я должен был прочитать javadoc ... Я пробовал и peek (), и isEmpty (), и оба всегда возвращают null или true.