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 утверждает, что это недопустимый вариант использования.