#java #multithreading #concurrency #java.util.concurrent
Вопрос:
Я читаю это:
В которой Дуг Леа говорит:
Обычно, когда вы помещаете что-то в очередь, вы только что выделили это новое что-то. И точно так же, когда вы что-то вынимаете, вы обычно используете это, а затем позволяете этому стать мусором. В этом случае дополнительное выделение для узла очереди не будет иметь большого значения для общего GC, поэтому вы можете также использовать лучшую масштабируемость LinkedBlockingQueue. Я думаю, что это наиболее распространенный вариант использования.
Но если вы не распределяете вещи, помещенные в очереди, и не ожидаете, что множество потоков будут конфликтовать, когда очередь не будет ни пустой, ни полной, то ArrayBlockingQueue, скорее всего, будет работать лучше.
Я хочу знать, что это Aren't allocating the things put into queues
значит?
Кроме того, это предложение: don't expect lots of threads to be contending when the queue is neither empty nor full, then ArrayBlockingQueue is likely to work better
, может ли кто-нибудь объяснить это немного более конкретно?
Комментарии:
1. Из контекста это, по-видимому, означает, что вещи, которые вы ставите в очередь, являются долгоживущими, т. е. кто-то уже выделил их давным-давно.
Ответ №1:
Для меня это, кажется, означает следующее:
-
Я хочу знать, что это
Aren't allocating the things put into queues
значит?Речь идет о накладных расходах GC, которые они обсуждают.
LinkedBlockingQueue
создает новый внутреннийNode
объект для каждого добавленного элемента, что означает, что он генерирует мусор и, как следствие, вызывает сборку мусора (GC).
Дуг говорит, что часто элементы, которые мы храним в очереди, являются объектами, которые:- создаются непосредственно перед добавлением в очередь
- становятся неиспользуемыми (и имеющими право на GC) вскоре после того, как они будут удалены из очереди
В этих случаях сами элементы в любом случае вызывают GC, поэтому не проблема, что
Node
объекты также требуют GC.Но если вы храните только долгоживущие объекты в очереди, это
LinkedBlockingQueue
может стать единственной причиной GC.
Тогда вы можете использоватьArrayBlockingQueue
вместо этого, чтобы избежать GC.
(ArrayBlockingQueue
не создает никаких объектов при добавлении/удалении элементов) -
Кроме того, это предложение:
don't expect lots of threads to be contending when the queue is neither empty nor full, then ArrayBlockingQueue is likely to work better
, может ли кто-нибудь объяснить это немного более конкретно?LinkedBlockingQueue
использует два замка: один дляput()
и один дляtake()
.
ArrayBlockingQueue
использует одну блокировку для обоихput()
иtake()
.
В результате , когда «the queue is neither empty nor full
» (т. Е. Когда ниput()
того, ниtake()
другого не нужно ждать) и есть два потока: один выполняетсяput()
, другой выполняетсяtake()
- если очередь есть
LinkedBlockingQueue
, то потоки не блокируют друг друга - если очередь есть
ArrayBlockingQueue
, то одному потоку придется подождать, пока другой не будет завершен
- если очередь есть
Комментарии:
1. Хорошо сказано. Единственное, что может сбить с толку ОП, — это тип долгоживущих объектов, о которых говорит Дуг Леа.