Интерфейс BlockingQueue в Java

Опубликовано: 5 Января, 2022

Интерфейс BlockingQueue в Java добавлен в Java 1.5 вместе с различными другими параллельными классами Utility, такими как ConcurrentHashMap, Counting Semaphore , CopyOnWriteArrrayList и т. Д. Интерфейс BlockingQueue поддерживает управление потоком (в дополнение к очереди) путем введения блокировки, если BlockingQueue заполнен или пуст. Поток, пытающийся поставить элемент в полную очередь, блокируется до тех пор, пока какой-либо другой поток не освободит место в очереди, либо исключив один или несколько элементов из очереди, либо полностью очистив очередь. Точно так же он блокирует поток, пытающийся удалить из пустой очереди, до тех пор, пока другие ступени не вставят элемент. BlockingQueue не принимает нулевое значение. Если мы попытаемся поставить в очередь нулевой элемент, он выбрасывает исключение NullPointerException .

Java предоставляет несколько реализаций BlockingQueue, таких как LinkedBlockingQueue, ArrayBlockingQueue, PriorityBlockingQueue, SynchronousQueue и т. Д. Реализации интерфейса Java BlockingQueue являются потокобезопасными. Все методы BlockingQueue являются атомарными по своей природе и используют внутренние блокировки или другие формы управления параллелизмом. Java 5 поставляется с реализациями BlockingQueue в пакете java.util.concurrent .

Использование BlockingQueue

BlockingQueue, доступ к которому осуществляется потоком-производителем (помещением) и потоком-потребителем (потоком получения)

Иерархия BlockingQueue

Декларация

 открытый интерфейс BlockingQueue <E> расширяет Queue <E>

Здесь E - это тип элементов, хранящихся в Коллекции.

Классы, реализующие BlockingQueue

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

 import java.util.concurrent.BlockingQueue;
                    (или)
import java.util.concurrent. *;
  • LinkedBlockingQueue
  • ArrayBlockingQueue

Класс реализации BlockingDeque - LinkedBlockingDeque. Этот класс является реализацией BlockingDeque и структуры данных связанного списка. LinkedBlockingDeque может быть дополнительно ограничен с помощью конструктора, однако, если емкость не указана, по умолчанию используется Integer.MAX_VALUE. Узлы добавляются динамически во время вставки в соответствии с ограничениями емкости.

Синтаксис для создания объектов:

 BlockingQueue <?> ObjectName = new LinkedBlockingDeque <?> ();   
                         (или)
LinkedBlockingDeque <?> ObjectName = new LinkedBlockingDeque <?> ();

Пример: В приведенном ниже коде мы выполняем некоторые базовые операции с LinkedBlockingDeque, такие как создание объекта, добавление элементов, удаление элементов и использование итератора для обхода LinkedBlockingDeque.

Типы BlockingQueue

BlockingQueue бывает двух типов :

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

Синтаксис:

 BlockingQueue blockingQueue = новый LinkedBlockingDeque ();

2. Ограниченная очередь . Второй тип очереди - это ограниченная очередь. В случае ограниченной очереди вы можете создать очередь, передавая емкость очереди в конструкторе очередей:

Синтаксис:

 // Создает блокирующую очередь емкостью 5
BlockingQueue blockingQueue = новый LinkedBlockingDeque (5);

Чтобы реализовать ограниченный семафор с помощью BlockingQueue

Джава

// Java program that explains the internal
// implementation of BlockingQueue
import java.io.*;
import java.util.*;
class BlockingQueue<E> {
// BlockingQueue using LinkedList structure
// with a constraint on capacity
private List<E> queue = new LinkedList<E>();
// limit variable to define capacity
private limit = int 10 ;
// constructor of BlockingQueue
public BlockingQueue( int limit) { this .limit = limit; }
// enqueue method that throws Exception
// when you try to insert after the limit
public synchronized void enqueue(E item)
throws InterruptedException
{
while ( this .queue.size() == this .limit) {
wait();
}
if ( this .queue.size() == 0 ) {
notifyAll();
}
this .queue.add(item);
}
// dequeue methods that throws Exception
// when you try to remove element from an
// empty queue
public synchronized E dequeue()
throws InterruptedException
{
while ( this .queue.size() == 0 ) {
wait();
}
if ( this .queue.size() == this .limit) {
notifyAll();
}
return this .queue.remove( 0 );
}
public static void main(String []args)
{
}
}


Пример:

Джава

// Java Program to demonstrate usuage of BlockingQueue
import java.util.concurrent.*;
import java.util.*;
public class GFG {
public static void main(String[] args)
throws InterruptedException
{
// define capacity of ArrayBlockingQueue
int capacity = 5 ;
// create object of ArrayBlockingQueue
BlockingQueue<String> queue
= new ArrayBlockingQueue<String>(capacity);
// Add elements to ArrayBlockingQueue using put
// method
queue.put( "StarWars" );
queue.put( "SuperMan" );
queue.put( "Flash" );
queue.put( "BatMan" );
queue.put( "Avengers" );
// print Queue
System.out.println( "queue contains " + queue);
// remove some elements
queue.remove();
queue.remove();
// Add elements to ArrayBlockingQueue
// using put method
queue.put( "CaptainAmerica" );
queue.put( "Thor" );
System.out.println( "queue contains " + queue);
}
}
Выход:
 очередь содержит [Звездные войны, Супермен, Флэш, Бэтмен, Мстители]
очередь содержит [Флэш, Бэтмен, Мстители, Капитан Америка, Тор]

Основные операции

1. Добавление элементов

Элементы могут быть добавлены в LinkedBlockedDeque по-разному в зависимости от типа структуры, в которой мы пытаемся ее использовать. Самый распространенный метод - это метод add (), с помощью которого мы можем добавлять элементы в конце двухсторонней очереди. Мы также можем использовать метод addAll () (который является методом интерфейса Collection), чтобы добавить всю коллекцию в LinkedBlockingDeque. Если мы хотим использовать двухстороннюю очередь как очередь, мы можем использовать add () и put ().

Джава

// Java Program Demonstrate add()
// method of BlockingQueue
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.BlockingQueue;
import java.util.*;
public class GFG {
public static void main(String[] args)
throws IllegalStateException
{
// create object of BlockingQueue
BlockingQueue<Integer> BQ
= new LinkedBlockingDeque<Integer>();
// Add numbers to the BlockingQueue
BQ.add( 7855642 );
BQ.add( 35658786 );
BQ.add( 5278367 );
BQ.add( 74381793 );
// before removing print BlockingQueue
System.out.println( "Blocking Queue: " + BQ);
}
}
Выход
 Очередь блокировки: [7855642, 35658786, 5278367, 74381793]

2. Доступ к элементам

Доступ к элементам LinkedBlockingDeque можно получить с помощью contains (), element (), peek (), poll (). Существуют также варианты этих методов, которые приведены в таблице выше вместе с их описанием.

Джава

// Java Program for Accessing the elements of a
// LinkedBlockingDeque
import java.util.concurrent.*;
public class AccessingElements {
public static void main(String[] args)
{
// Instantiate an object of LinkedBlockingDeque
// named lbdq
BlockingQueue<Integer> lbdq
= new LinkedBlockingDeque<Integer>();
// Add elements using add()
lbdq.add( 22 );
lbdq.add( 125 );
lbdq.add( 723 );
lbdq.add( 172 );
lbdq.add( 100 );
// Print the elements of lbdq on the console
System.out.println(
"The LinkedBlockingDeque, lbdq contains:" );
System.out.println(lbdq);
// To check if the deque contains 22
if (lbdq.contains( 22 ))
System.out.println(
"The LinkedBlockingDeque, lbdq contains 22" );
else
System.out.println( "No such element exists" );
// Using element() to retrieve the head of the deque
int head = lbdq.element();
System.out.println( "The head of lbdq: " + head);
}
}
Выход
 LinkedBlockingDeque, lbdq содержит:
[22, 125, 723, 172, 100]
LinkedBlockingDeque, lbdq содержит 22
Глава лбдк: 22

3. Удаление элементов

Элементы могут быть удалены из LinkedBlockingDeque с помощью remove (). Другие методы, такие как take () и poll (), также могут использоваться для удаления первого и последнего элементов.

Джава

// Java Program for removing elements from a
// LinkedBlockingDeque
import java.util.concurrent.*;
public class RemovingElements {
public static void main(String[] args)
{
// Instantiate an object of LinkedBlockingDeque
// named lbdq
BlockingQueue<Integer> lbdq
= new LinkedBlockingDeque<Integer>();
// Add elements using add()
lbdq.add( 75 );
lbdq.add( 86 );
lbdq.add( 13 );
lbdq.add( 44 );
lbdq.add( 10 );
// Print the elements of lbdq on the console
System.out.println(
"The LinkedBlockingDeque, lbdq contains:" );
System.out.println(lbdq);
// Remove elements using remove();
lbdq.remove( 86 );
lbdq.remove( 44 );
// Trying to remove an element
// that doesn't exist
// in the LinkedBlockingDeque
lbdq.remove( 1 );
// Print the elements of lbdq on the console
System.out.println(
" The LinkedBlockingDeque, lbdq contains:" );
System.out.println(lbdq);
}
}
Выход
 LinkedBlockingDeque, lbdq содержит:
[75, 86, 13, 44, 10]

LinkedBlockingDeque, lbdq содержит:
[75, 13, 10]

4. Перебор элементов

Чтобы перебирать элементы LinkedBlockingDeque, мы можем создать итератор и использовать методы интерфейса Iterable, который является корнем Collection Framework Java, для доступа к элементам. Метод next () класса Iterable возвращает элемент любой коллекции.

Джава

// Java Program to iterate
// through the LinkedBlockingDeque
import java.util.Iterator;
import java.util.concurrent.*;
public class IteratingThroughElements {
public static void main(String[] args) {
// Instantiate an object of LinkedBlockingDeque named lbdq
BlockingQueue<Integer> lbdq = new LinkedBlockingDeque<Integer>();
// Add elements using add()
lbdq.add( 166 );
lbdq.add( 246 );
lbdq.add( 66 );
lbdq.add( 292 );
lbdq.add( 98 );
// Create an iterator to traverse lbdq
Iterator<Integer> lbdqIter = lbdq.iterator();
// Print the elements of lbdq on to the console
System.out.println( "The LinkedBlockingDeque, lbdq contains:" );
for ( int i = 0 ; i<lbdq.size(); i++)
{
System.out.print(lbdqIter.next() + " " );
}
}
}
Выход
 LinkedBlockingDeque, lbdq содержит:
166 246 66 292 98

Методы BlockingQueue

МЕТОД

ОПИСАНИЕ

добавить (E e) Вставляет указанный элемент в эту очередь, если это возможно сделать немедленно, без нарушения ограничений емкости, возвращая true в случае успеха и генерируя исключение IllegalStateException, если в данный момент нет свободного места.
содержит (Объект o) Возвращает истину, если эта очередь содержит указанный элемент.
DrainTo (Коллекция <? super E> c) Удаляет все доступные элементы из этой очереди и добавляет их в данную коллекцию.
DrainTo (Коллекция <? super E> c, int maxElements) Удаляет не более указанного количества доступных элементов из этой очереди и добавляет их в данную коллекцию.
предложение (E e) Вставляет указанный элемент в эту очередь, если это возможно сделать немедленно, не нарушая ограничений емкости, возвращая истину в случае успеха и ложь, если в данный момент нет свободного места.
предложение (E e, длительный тайм-аут, единица TimeUnit) Вставляет указанный элемент в эту очередь, ожидая до указанного времени ожидания, если необходимо, чтобы пространство стало доступным.
опрос (длинный таймаут, единица TimeUnit) Извлекает и удаляет заголовок этой очереди, ожидая до указанного времени ожидания, если необходимо, чтобы элемент стал доступным.
положить (E e) Вставляет указанный элемент в эту очередь, ожидая, если необходимо, освободится место.
оставшаяся емкость () Возвращает количество дополнительных элементов, которые эта очередь может идеально (при отсутствии ограничений памяти или ресурсов) принять без блокировки, или Integer.MAX_VALUE, если нет внутреннего ограничения.
удалить (Объект o) Удаляет единственный экземпляр указанного элемента из этой очереди, если он присутствует.
брать() Извлекает и удаляет заголовок этой очереди, при необходимости ожидая, пока элемент не станет доступным.

Методы, объявленные в интерфейсе java.util.Collection

МЕТОД

ОПИСАНИЕ

addAll (Коллекция <? extends E> c) Добавляет все элементы указанной коллекции в эту коллекцию (необязательная операция).
Чисто() Удаляет все элементы из этой коллекции (необязательная операция).
containsAll (Коллекция <?> c) Возвращает true, если эта коллекция содержит все элементы указанной коллекции.
равно (Объект o) Сравнивает указанный объект с этой коллекцией на равенство.
хэш-код() Возвращает значение хэш-кода для этой коллекции.
пустой() Возвращает true, если эта коллекция не содержит элементов.
итератор () Возвращает итератор по элементам в этой коллекции.
parallelStream () Возвращает возможно параллельный Stream с этой коллекцией в качестве источника.
removeAll (Коллекция <?> c) Удаляет все элементы этой коллекции, которые также содержатся в указанной коллекции (необязательная операция).
removeIf (фильтр Predicate <? super E>) Удаляет все элементы этой коллекции, удовлетворяющие заданному предикату.
keepAll (Коллекция <?> c) Сохраняет только те элементы в этой коллекции, которые содержатся в указанной коллекции (необязательная операция).
размер() Возвращает количество элементов в этой коллекции.
сплитератор () Создает Spliterator над элементами в этой коллекции.
транслировать() Возвращает последовательный Stream с этой коллекцией в качестве источника.
toArray () Возвращает массив, содержащий все элементы в этой коллекции.
toArray (генератор IntFunction <T []>) Возвращает массив, содержащий все элементы в этой коллекции, используя предоставленную функцию генератора для выделения возвращенного массива.
toArray (T [] a) Возвращает массив, содержащий все элементы в этой коллекции; тип среды выполнения возвращаемого массива - это тип указанного массива.

Методы, объявленные в интерфейсе java.lang.Iterable

МЕТОД

ОПИСАНИЕ

forEach (действие Consumer <? super T>) Выполняет заданное действие для каждого элемента Iterable до тех пор, пока все элементы не будут обработаны или действие не вызовет исключение.

Методы, объявленные в интерфейсе java.util.Queue

МЕТОД

ОПИСАНИЕ

элемент() Извлекает, но не удаляет заголовок этой очереди.
заглянуть () Извлекает, но не удаляет заголовок этой очереди, или возвращает null, если эта очередь пуста.
опрос() Извлекает и удаляет заголовок этой очереди или возвращает null, если эта очередь пуста.
Удалить() Извлекает и удаляет заголовок этой очереди.

Поведение методов BlockingQueue

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

  • Выдает исключение: будет выброшено исключение, если запрошенная операция не будет удовлетворена немедленно.
  • Специальное значение: специальное значение возвращается, если операция не выполняется немедленно.
  • Блокирует: вызов метода блокируется, если предпринятая операция не выполняется немедленно, и он ждет, пока не будет выполнен.
  • Тайм-аут: возвращается специальное значение, показывающее, была ли операция успешной или нет. Если запрошенная операция невозможна немедленно, вызов метода блокируется до тех пор, пока она не станет доступной, но не ждет дольше заданного тайм-аута.
Операция Выбрасывает исключение Особая ценность Блоки Время вышло
Вставлять добавить (е) предложение (е) положить (е) предложение (е, время, единица)
Удалять Удалить() опрос() брать() опрос (время, единица)
Исследовать элемент() заглянуть () непригодный непригодный

Ссылка: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/BlockingQueue.html

Вниманию читателя! Не прекращайте учиться сейчас. Ознакомьтесь со всеми важными концепциями Java Foundation и коллекций с помощью курса "Основы Java и Java Collections" по доступной для студентов цене и будьте готовы к работе в отрасли. Чтобы завершить подготовку от изучения языка к DS Algo и многому другому, см. Полный курс подготовки к собеседованию .