Почему ArrayBlockingQueue называется ограниченной очередью, а LinkedBlockingQueue называется неограниченной очередью блокировки?

Насколько я знаю, и связанный список, и массив могут расти без ограничений, или я ошибаюсь? Но когда я прошел через документация в Executor Service Я вижу это:

Неограниченные очереди. Использование неограниченной очереди (например, LinkedBlockingQueue без предопределенной емкости) приведет к тому, что новые задачи будут ожидать в очереди, когда все потоки corePoolSize будут заняты. Таким образом, никогда не будет создано больше потоков corePoolSize. (Поэтому значение maxPoolSize не имеет никакого эффекта.)

Изменяется ли свойство Unbounded Queue, когда LinkedBlockingQueue имеет определенную емкость?

А это написано для ArrayBlockingQueue:

Ограниченные очереди. Ограниченная очередь (например, ArrayBlockingQueue) помогает предотвратить исчерпание ресурсов при использовании с конечными максимальными размерами пула, но ее сложнее настраивать и контролировать. Размеры очередей и максимальные размеры пулов могут компенсироваться друг другом: использование больших очередей и малых пулов минимизирует использование ЦП, ресурсов ОС и накладных расходов на переключение контекста, но может привести к искусственно заниженной пропускной способности. Если задачи часто блокируются (например, если они связаны с вводом-выводом), система может запланировать время для большего количества потоков, чем вы разрешаете в противном случае. Использование небольших очередей обычно требует больших размеров пула, что увеличивает нагрузку на ЦП, но может привести к неприемлемым издержкам планирования, что также снижает пропускную способность.


person Geek    schedule 06.08.2012    source источник


Ответы (5)


Как вы думаете, почему ArrayBlockingQueue может расти без ограничений? Из его собственной документации:

Это классический «ограниченный буфер», в котором массив фиксированного размера содержит элементы, вставленные производителями и извлеченные потребителями. После создания емкость не может быть увеличена. Попытки поставить элемент в полную очередь приведут к блокировке операции; попытки взять элемент из пустой очереди будут аналогичным образом блокироваться.

Другими словами, когда он наполняется, он наполняется — он не растет.

Вы случайно не запутались с ArrayList, который также поддерживается массивом, но который расширяет его по мере необходимости?

Изменяется ли свойство Unbounded Queue, когда LinkedBlockingQueue имеет определенную емкость?

Да, поэтому он описан как «необязательно ограниченный» в его Javadocs. Кроме того, в документах говорится, что (выделено мной):

Необязательный аргумент конструктора ограничения емкости служит способом предотвращения чрезмерного расширения очереди. Емкость, если она не указана, равна Integer.MAX_VALUE. Связанные узлы создаются динамически при каждой вставке, если только это не приведет к превышению емкости очереди.

person Andrzej Doyle    schedule 06.08.2012
comment
@Andrej Да, я путаю ArrayList с Array. Спасибо за разъяснение. Кстати, как растет ArrayList, когда он поддерживается базовым массивом, который не может расти? - person Geek; 06.08.2012
comment
Когда необходимо изменить размер, ArrayList выделяет новый массив большего размера и копирует все элементы в этот новый массив. - person Louis Wasserman; 06.08.2012

В javadoc для LinkedBlockingQueue говорится:

Опционально ограниченная очередь блокировки на основе связанных узлов.[...]

Необязательный аргумент конструктора ограничения емкости служит способом предотвращения чрезмерного расширения очереди. Емкость, если она не указана, равна Integer.MAX_VALUE.

В javadoc ArrayBlockingQueue говорится:

Ограниченная очередь блокировки, поддерживаемая массивом.[...]

Это классический «ограниченный буфер», в котором массив фиксированного размера содержит элементы, вставленные производителями и извлеченные потребителями. После создания емкость не может быть увеличена

Таким образом, LinkedBlockingQueue может быть ограниченной или неограниченной, тогда как ArrayBlockingQueue всегда ограничена.

person JB Nizet    schedule 06.08.2012

Насколько я знаю, и связанный список, и массив могут расти без ограничений, или я ошибаюсь?

Связанный список неограниченного размера. Массив имеет фиксированный размер. ArrayList упаковывает массив и заменяет его, когда ему нужен больший.

Также изменяется свойство Unbounded Queue, когда LinkedBlockingQueue имеет определенную емкость.

Когда LinkedBlockingQueue имеет максимальную емкость, она ограничена, но не используется по умолчанию.

person Peter Lawrey    schedule 06.08.2012
comment
ArrayList обертывает массив и заменяет его, когда ему нужен больший. Вы можете увидеть это в методе sureCapacity для ArrayList. - person Peter Lawrey; 06.08.2012

Из документации для ArrayBlockingQueue

Ограниченная блокирующая очередь, поддерживаемая массивом. Эта очередь упорядочивает элементы FIFO (первым пришел-первым обслужен). Голова очереди — это тот элемент, который находится в очереди дольше всего. Хвост очереди — это тот элемент, который находился в очереди наименьшее время. Новые элементы вставляются в конец очереди, а операции извлечения из очереди получают элементы в начале очереди.

Если вы заметили, что все конструкторы ArrayBlockingQueue используют емкость, потому что этот класс был разработан для ограничения. Этот выбор был сделан потому, что если вам нужна одновременная очередь, вам, вероятно, не нужны накладные расходы, связанные с изменением размера ArrayList. Следовательно, если вам нужна неограниченная очередь, LinkedBlockingQueue — лучший вариант, поскольку он не требует дополнительных затрат.

person John B    schedule 06.08.2012

другой ответ очень правильный! Я предлагаю другой способ объяснить. ну меня тоже смущает пропущенный термин "несвязанный и связанный". вы можете посмотреть исходный код.

    /** The queued items */
final Object[] items;

/** items index for next take, poll, peek or remove */
int takeIndex;

/** items index for next put, offer, or add */
int putIndex;

/** Number of elements in the queue */
int count;

из исходного кода мы видим, что массив является окончательным, поэтому мы не можем изменить размер массива. если использовать LinkedBlockingQueue, мы всегда можем добавить дополнительные элементы... и в исходном коде следующая ссылка не является окончательной. ПРИМЕЧАНИЕ. Теоретически LinkedBlockingQueue не является неограниченной. потому что он может хранить только MAX_INTEGER минус 8 элементов. из javadoc неограниченная очередь PriorityBlockingQueue. но PriorityBlockingQueue также может хранить только MAX_INTEGER -8 элементов. поэтому я думаю, что идеальной неограниченной очереди не существует...

person wannibar    schedule 03.02.2018