Ограниченная емкость BlockingQueue
также полезна, если вы хотите ограничить какой-либо запрос. С неограниченной очередью производители могут значительно опередить потребителей. Задачи в конечном итоге будут выполнены (если только их не будет столько, что они вызовут OutOfMemoryError
), но производитель может уже давно сдаться, поэтому усилия будут потрачены впустую.
В подобных ситуациях может быть лучше сообщить потенциальному производителю, что очередь заполнена, и быстро отказаться от ошибки. Например, источником может быть веб-запрос с пользователем, который не хочет ждать слишком долго, и хотя он не будет потреблять много циклов ЦП во время ожидания, он использует ограниченные ресурсы, такие как сокет и некоторое количество памяти. , Отказ предоставит поставленным в очередь задачам лучший шанс для своевременного завершения.
Относительно измененного вопроса, который я интерпретирую как «Что такое хорошая коллекция для хранения объектов в пуле?»
Неограниченный LinkedBlockingQueue
- хороший выбор для многих пулов. Однако, в зависимости от вашей стратегии управления пулом, ConcurrentLinkedQueue
может также работать.
В приложении для пула блокирующий «пут» не подходит. Управление максимальным размером очереди является задачей менеджера пула - он решает, когда создавать или уничтожать ресурсы для пула. Клиенты пула заимствуют и возвращают ресурсы из пула. Добавление нового объекта или возврат ранее заимствованного объекта в пул должны быть быстрыми, не блокирующими операциями. Таким образом, очередь с ограниченной емкостью не подходит для пулов.
С другой стороны, при извлечении объекта из пула большинству приложений требуется ждать, пока ресурс не станет доступен. Операция «take», которая блокирует, по крайней мере временно, гораздо более эффективна, чем «ожидание занятости» - многократный опрос, пока ресурс не станет доступным. LinkedBlockingQueue
- хороший выбор в этом случае. Заемщик может заблокировать на неопределенный срок с помощью take
или ограничить время, которое он желает заблокировать, с помощью poll
.
Менее распространенный случай, когда клиент вообще не хочет блокировать, но имеет возможность создать ресурс для себя, если пул пуст. В этом случае ConcurrentLinkedQueue
- хороший выбор. Это своего рода серая область, где было бы неплохо разделить ресурс (например, память) как можно больше, но скорость еще важнее. В худшем случае это вырождается в каждый поток, имеющий свой собственный экземпляр ресурса; тогда было бы эффективнее не пытаться делиться между потоками.
Обе эти коллекции обеспечивают хорошую производительность и простоту использования в параллельном приложении. Для непараллельных приложений трудно набрать ArrayList
. Даже для коллекций, которые растут динамически, накладные расходы на элемент LinkedList
позволяют ArrayList
с некоторыми пустыми слотами оставаться конкурентоспособными в отношении памяти.