java BlockingQueue не имеет блокирующего взгляда?
У меня есть блокирующая очередь объектов.
Я хочу написать поток, который блокирует, пока в очереди нет объекта. Аналогично функциональности, предоставляемой BlockingQueue.брать.)(
однако, поскольку я не знаю, смогу ли я успешно обработать объект, я хочу просто заглянуть() и не удалять объект. Я хочу удалить объект только в том случае, если я смогу его успешно обработать.
Итак, я хотел бы функцию блокировки peek (). В настоящий момент, peek () просто возвращает, если очередь пуста согласно javadocs.
Я что-то пропустила? Есть ли другой способ достижения этой функции?
EDIT:
любые мысли о том, если я просто использовал потокобезопасную очередь и подсматривал и спал вместо этого?
public void run() {
while (!__exit) {
while (__queue.size() != 0) {
Object o = __queue.peek();
if (o != null) {
if (consume(o) == true) {
__queue.remove();
} else {
Thread.sleep(10000); //need to backoff (60s) and try again
}
}
}
Thread.sleep(1000); //wait 1s for object on queue
}
}
обратите внимание, что у меня есть только один поток потребителя и один (отдельный) поток производителя. Я думаю, это не так эффективно, как использование BlockingQueue... Любые комментарии приветствуются.
7 ответов
вы могли бы использовать LinkedBlockingDeque и физически удалить элемент из очереди (используя takeLast()
), но заменить его снова на конец очереди если обработка не удается с помощью putLast(E e)
. Между тем ваши "производители" добавят элементы в перед очереди с помощью putFirst(E e)
.
вы всегда можете инкапсулировать это поведение в своем собственном Queue
реализация и предоставление blockingPeek()
метод, который выполняет takeLast()
затем putLast()
за кулисами на базовом LinkedBlockingDeque
. Следовательно, с точки зрения вызывающего клиента элемент никогда не удаляется из вашей очереди.
однако, поскольку я не знаю, смогу ли я успешно обработать объект, я хочу просто заглянуть() и не удалять объект. Я хочу удалить объект только в том случае, если я смогу его успешно обработать.
В общем, это не является потокобезопасным. Что, если после тебя ... --0--> и определить, что объект может быть успешно обработаны, но перед take()
Он для удаления и обработки, другой поток принимает этот объект?
единственное, что я знаю, что это такое BlockingBuffer на Коллекции Apache Commons:
если вызывается get или remove пустой буфер, вызывающий поток ожидает уведомления о том, что add или добавим операция завершена.
get()
эквивалентно peek()
и Buffer
можно заставить действовать как BlockingQueue
купить украшения UnboundedFifoBuffer С a BlockingBuffer
не могли бы вы также просто добавить очередь прослушивателя событий в свою очередь блокировки, а затем, когда что-то добавляется в очередь (блокировки), отправьте событие своим слушателям? Вы можете иметь свой блок потока, пока не будет вызван метод actionPerformed.
быстрый ответ заключается в том, что на самом деле нет способа иметь блокирующий взгляд, бар, реализующий блокирующую очередь с блокирующим взглядом ().
Я что-то пропустила?
peek () может быть хлопотно с параллелизмом -
- если вы не можете обработать сообщение peek()'d - оно будет оставлено в очереди, если у вас нет нескольких потребителей.
- кто собирается получить этот объект из очереди, если вы не можете его обработать ?
- если у вас несколько потребителей, вы получаете условие гонки между вами peek () и другим потоком, также обрабатывающим элементы, что приводит к дублированию обработки или хуже.
звучит так, как будто вам может быть лучше удалить элемент и обработать его с помощью цепь ответственности шаблон
Edit: re: ваш последний пример: если у вас есть только 1 потребитель, вы никогда не избавитесь от объекта в очереди-если он не будет обновлен в среднее время - в этом случае вам лучше быть очень осторожным с безопасностью потоков и, вероятно, не следовало ставить элемент в очередь в любом случае.
похоже, что сам BlockingQueue не имеет указанной вами функциональности.
Я мог бы попытаться немного переформулировать проблему: что бы вы сделали с объектами, которые вы не можете "обработать правильно"? Если вы просто оставляете их в очереди, вам придется вытащить их в какой-то момент и разобраться с ними. Я бы рекомендовал либо выяснить, как их обрабатывать (обычно, если очередь.get () дает любое недопустимое или плохое значение, вы, вероятно, в порядке, чтобы просто бросить его на floor) или выбор другой структуры данных, чем FIFO.
Не ответ как таковой, но: JDK-6653412 утверждает, что это недопустимый вариант использования.