Что означает «Не распределяете вещи, помещенные в очереди»?

#java #multithreading #concurrency #java.util.concurrent

Вопрос:

Я читаю это:

https://concurrency.markmail.org/search/?q=ArrayBlockingQueue LinkedBlockingQueue#query:ArrayBlockingQueue LinkedBlockingQueue from:»Doug Lea» page:1 mid:sgx3amdfga7esqul state:results

В которой Дуг Леа говорит:

Обычно, когда вы помещаете что-то в очередь, вы только что выделили это новое что-то. И точно так же, когда вы что-то вынимаете, вы обычно используете это, а затем позволяете этому стать мусором. В этом случае дополнительное выделение для узла очереди не будет иметь большого значения для общего 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:

Для меня это, кажется, означает следующее:

  1. Я хочу знать, что это Aren't allocating the things put into queues значит?

    Речь идет о накладных расходах GC, которые они обсуждают.

    LinkedBlockingQueue создает новый внутренний Node объект для каждого добавленного элемента, что означает, что он генерирует мусор и, как следствие, вызывает сборку мусора (GC).
    Дуг говорит, что часто элементы, которые мы храним в очереди, являются объектами, которые:

    • создаются непосредственно перед добавлением в очередь
    • становятся неиспользуемыми (и имеющими право на GC) вскоре после того, как они будут удалены из очереди

    В этих случаях сами элементы в любом случае вызывают GC, поэтому не проблема, что Node объекты также требуют GC.

    Но если вы храните только долгоживущие объекты в очереди, это LinkedBlockingQueue может стать единственной причиной GC.
    Тогда вы можете использовать ArrayBlockingQueue вместо этого, чтобы избежать GC.
    ( ArrayBlockingQueue не создает никаких объектов при добавлении/удалении элементов)

  2. Кроме того, это предложение: 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. Хорошо сказано. Единственное, что может сбить с толку ОП, — это тип долгоживущих объектов, о которых говорит Дуг Леа.