Рубрики
Без рубрики

LinkedBlockingQueue против concurrentlink queue

Узнайте разницу между LinkedBlockingQueue и Concurrentlink queue в Java

Автор оригинала: baeldung.

1. введение

LinkedBlockingQueue и ConcurrentLinkedQueue являются двумя наиболее часто используемыми параллельными очередями в Java . Хотя обе очереди часто используются в качестве параллельной структуры данных, между ними существуют тонкие характеристики и поведенческие различия.

В этом коротком уроке мы обсудим обе эти очереди и объясним их сходства и различия.

2. LinkedBlockingQueue

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

Давайте создадим LinkedBlockingQueue , который может содержать до 100 элементов:

BlockingQueue boundedQueue = new LinkedBlockingQueue<>(100);

Мы также можем создать неограниченный LinkedBlockingQueue , просто не указав размер:

BlockingQueue unboundedQueue = new LinkedBlockingQueue<>();

Неограниченная очередь подразумевает, что размер очереди не задается при создании. Таким образом, очередь может динамически расти по мере добавления в нее элементов. Однако, если памяти не осталось, то очередь выдает java.lang.OutOfMemoryError.

Мы также можем создать LinkedBlockingQueue из существующей коллекции:

Collection listOfNumbers = Arrays.asList(1,2,3,4,5);
BlockingQueue queue = new LinkedBlockingQueue<>(listOfNumbers);

Класс LinkedBlockingQueue | реализует интерфейс BlockingQueue , который обеспечивает ему блокирующий характер .

Очередь блокировки указывает, что очередь блокирует поток доступа, если она заполнена (когда очередь ограничена) или становится пустой. Если очередь заполнена, то добавление нового элемента заблокирует поток доступа, если для нового элемента не будет свободного места. Аналогично, если очередь пуста, то доступ к элементу блокирует вызывающий поток:

ExecutorService executorService = Executors.newFixedThreadPool(1);
LinkedBlockingQueue queue = new LinkedBlockingQueue<>();
executorService.submit(() -> {
  try {
    queue.take();
  } 
  catch (InterruptedException e) {
    // exception handling
  }
});

В приведенном выше фрагменте кода мы обращаемся к пустой очереди. Поэтому метод take блокирует вызывающий поток.

Функция блокировки LinkedBlockingQueue связана с некоторыми затратами. Эта стоимость связана с тем, что каждая операция put или take блокируется между потоками производителя или потребителя. Поэтому в сценариях со многими производителями и потребителями положить и предпринять действия могут быть медленнее.

3. Concurrentlink queue

A Concurrentlink Queue -это неограниченная, потокобезопасная и неблокирующая очередь.

Давайте создадим пустой Concurrentlink queue :

ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue();

Мы также можем создать Concurrentlink queue из существующей коллекции:

Collection listOfNumbers = Arrays.asList(1,2,3,4,5);
ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue<>(listOfNumbers);

В отличие от LinkedBlockingQueue, |/a Concurrentlink queue является неблокирующей очередью . Таким образом, он не блокирует поток, как только очередь пуста. Вместо этого он возвращает null . Поскольку он неограничен, он будет выдавать java.lang.OutOfMemoryError если нет дополнительной памяти для добавления новых элементов.

Помимо того, что он не блокируется, Concurrentlink queue имеет дополнительную функциональность.

В любом сценарии “производитель-потребитель” потребители не будут довольствоваться производителями; однако несколько производителей будут бороться друг с другом:

int element = 1;
ExecutorService executorService = Executors.newFixedThreadPool(2);
ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue<>();

Runnable offerTask = () -> queue.offer(element);

Callable pollTask = () -> {
  while (queue.peek() != null) {
    return queue.poll().intValue();
  }
  return null;
};

executorService.submit(offerTask);
Future returnedElement = executorService.submit(pollTask);
assertThat(returnedElement.get().intValue(), is(equalTo(element)));

Первая задача, после задачи , добавляет элемент в очередь, а вторая задача, Задача пула, извлекает элемент из очереди. Задача опроса дополнительно сначала проверяет очередь на наличие элемента, поскольку Concurrentlink queue не блокируется и может возвращать null значение .

4. Сходство

Оба LinkedBlockingQueue и Concurrentlink queue являются реализациями очереди и имеют некоторые общие характеристики. Давайте обсудим сходство этих двух очередей:

  1. Оба реализуют Очередь Интерфейс
  2. Они оба используют связанные узлы для хранения своих элементов
  3. Оба подходят для сценариев параллельного доступа

5. Различия

Хотя обе эти очереди имеют определенное сходство, существуют также существенные различия в характеристиках:

Блокирующая природа Это блокирующая очередь и реализует интерфейс BlockingQueue Это неблокирующая очередь и не реализует интерфейс BlockingQueue
Размер очереди Это необязательно ограниченная очередь, что означает, что существуют положения для определения размера очереди во время создания Это неограниченная очередь, и нет никаких условий для указания размера очереди во время создания
Запирающая природа Это очередь на основе блокировки Это очередь без блокировки
Алгоритм Он реализует свою блокировку на основе алгоритма очереди с двумя блокировками Он опирается на алгоритм Майкла и Скотта для неблокирующих, свободных от блокировки очередей
Реализация В механизме алгоритма очереди с двумя блокировками LinkedBlockingQueue использует две разные блокировки – putLock и TakeLock. Операции put/take используют первый тип блокировки, а операции take/poll-другой тип блокировки Он использует CAS (Compare-And-Swap) для своих операций
Поведение Блокировки Это блокирующая очередь. Таким образом, он блокирует потоки доступа, когда очередь пуста Он не блокирует поток доступа, когда очередь пуста, и возвращает null

6. Заключение

В этой статье мы узнали о LinkedBlockingQueue и Concurrentlink queue.

Во-первых, мы отдельно обсудили эти две реализации очередей и некоторые их характеристики. Затем мы увидели сходство между этими двумя реализациями очередей. Наконец, мы исследовали различия между этими двумя реализациями очередей.

Как всегда, исходный код примеров доступен на GitHub .