Ответ 1
Борис Паук уже обозначил наиболее заметную разницу между ArrayBlockingQueue
и LinkedBlockingQueue
- первая всегда ограничена, а последняя может быть неограниченной.
Поэтому, если вам нужна неограниченная блокирующая очередь, LinkedBlockingQueue
или LinkedTransferQueue
, используемые в качестве BlockingQueue
, являются вашими лучшими ставками из панели инструментов java.util.concurrent
.
Но скажем, вам нужна ограниченная блокирующая очередь. В конце концов, вы должны выбрать реализацию, основанную на обширных экспериментах с симуляцией вашей реальной рабочей нагрузки. Тем не менее, вот некоторые заметки, которые могут помочь вам по вашему выбору или интерпретировать результаты эксперимента:
-
ArrayBlockingQueue
может быть создан с помощью настраиваемой (вкл/выкл) политики справедливости планирования. Это здорово, если вам нужна справедливость или вы хотите избежать голода продюсера/потребителя, но это будет стоить вам пропускной способности. -
ArrayBlockingQueue
предварительно выделяет свой базовый массив, поэтому он не выделяет узлы во время его использования, но он сразу принимает то, что может быть значительным портом памяти, что может быть проблемой, если ваша память фрагментирована. -
ArrayBlockingQueue
должен иметь меньшую изменчивость в производительности, поскольку он имеет меньше движущихся частей в целом, он использует более простой и менее сложный алгоритм с одним замком, он не создает узлы во время использования, а его поведение в кэше должно быть достаточно последовательным. -
LinkedBlockingQueue
должен иметь лучшую пропускную способность, поскольку он использует отдельные блокировки для головы и хвоста. -
LinkedBlockingQueue
не предварительно выделяет узлы, а это означает, что его объем памяти будет примерно соответствовать его размеру, но это также означает, что он будет выполнять некоторую работу по распределению и освобождению узлов. -
LinkedBlockingQueue
, вероятно, будет иметь более худшее поведение в кэше, что может повлиять на его собственную производительность, а также производительность других компонентов из-за ложного обмена.
В зависимости от вашего прецедента и насколько вы заботитесь о производительности, вы также можете посмотреть вне java.util.concurrent
и рассмотреть Disruptor (исключительно быстрый, но несколько специализированный ограниченный неблокирующий кольцевой буфер) или JCTools (множество ограниченных или неограниченных очередей с различные гарантии в зависимости от количества производителей и потребителей).