Когда предпочитаете LinkedBlockingQueue над ArrayBlockingQueue?

Когда предпочитаете LinkedBlockingQueue over ArrayBlockingQueue?

Какую структуру данных следует использовать между LinkedBlockingQueue и ArrayBlockingQueue, когда:

  • Вы хотите эффективно читать и писать
  • должен иметь меньшие следы памяти

Хотя есть аналогичный вопрос, но он не подчеркивает того, что должно быть предпочтительным?

Ссылки:

Ответ 1

Борис Паук уже обозначил наиболее заметную разницу между ArrayBlockingQueue и LinkedBlockingQueue - первая всегда ограничена, а последняя может быть неограниченной.

Поэтому, если вам нужна неограниченная блокирующая очередь, LinkedBlockingQueue или LinkedTransferQueue, используемые в качестве BlockingQueue, являются вашими лучшими ставками из панели инструментов java.util.concurrent.

Но скажем, вам нужна ограниченная блокирующая очередь. В конце концов, вы должны выбрать реализацию, основанную на обширных экспериментах с симуляцией вашей реальной рабочей нагрузки. Тем не менее, вот некоторые заметки, которые могут помочь вам по вашему выбору или интерпретировать результаты эксперимента:

  • ArrayBlockingQueue может быть создан с помощью настраиваемой (вкл/выкл) политики справедливости планирования. Это здорово, если вам нужна справедливость или вы хотите избежать голода продюсера/потребителя, но это будет стоить вам пропускной способности.
  • ArrayBlockingQueue предварительно выделяет свой базовый массив, поэтому он не выделяет узлы во время его использования, но он сразу принимает то, что может быть значительным портом памяти, что может быть проблемой, если ваша память фрагментирована.
  • ArrayBlockingQueue должен иметь меньшую изменчивость в производительности, поскольку он имеет меньше движущихся частей в целом, он использует более простой и менее сложный алгоритм с одним замком, он не создает узлы во время использования, а его поведение в кэше должно быть достаточно последовательным.
  • LinkedBlockingQueue должен иметь лучшую пропускную способность, поскольку он использует отдельные блокировки для головы и хвоста.
  • LinkedBlockingQueue не предварительно выделяет узлы, а это означает, что его объем памяти будет примерно соответствовать его размеру, но это также означает, что он будет выполнять некоторую работу по распределению и освобождению узлов.
  • LinkedBlockingQueue, вероятно, будет иметь более худшее поведение в кэше, что может повлиять на его собственную производительность, а также производительность других компонентов из-за ложного обмена.

В зависимости от вашего прецедента и насколько вы заботитесь о производительности, вы также можете посмотреть вне java.util.concurrent и рассмотреть Disruptor (исключительно быстрый, но несколько специализированный ограниченный неблокирующий кольцевой буфер) или JCTools (множество ограниченных или неограниченных очередей с различные гарантии в зависимости от количества производителей и потребителей).

Ответ 2

Из JavaDoc для ArrayBlockingQueue

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

Акцент на мине

Из JavaDoc для LinkedBlockingQueue:

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

Акцент на мине

Итак, если вам нужна ограниченная очередь, вы можете использовать либо, если вам нужна неограниченная очередь, вы должны использовать LinkedBlockingQueue.

Для ограниченной очереди вам нужно будет проверить, что лучше.

Ответ 3

Оба из них реализуют BlockingQueue. Как следует из названия, arrayBlockingQueue поддерживается Array, тогда как LinkedBlockingQueue поддерживается linked list.

Какой из них выбрать, по существу, должен быть таким же, как причина выбора между ArrayList и LinkedList

Добавление элемента в arrayBlockingQueue должно быть быстрее, поскольку оно означает только установку ссылки на элемент массива объектов Backing, в то время как добавление элемента в LinkedBlockingQueue означает создание Node и установку его элемента, prev и next. Кроме того, когда мы удаляем элемент из LinkedBlockingQueue, удаленный Node становится мусором, который может влиять на производительность приложения.