Interfaz BlockingQueue en Java

La interfaz BlockingQueue en Java se agrega en Java 1.5 junto con varias otras clases de utilidades concurrentes como ConcurrentHashMap , Counting Semaphore , CopyOnWriteArrrayLis t, etc. La interfaz BlockingQueue admite el control de flujo (además de la cola) al introducir el bloqueo si BlockingQueue está lleno o vacío. Un subproceso que intenta poner en cola un elemento en una cola completa se bloquea hasta que otro subproceso hace espacio en la cola, ya sea eliminando uno o más elementos o borrando la cola por completo. De manera similar, bloquea un subproceso que intenta eliminar de una cola vacía hasta que otros subprocesos insertan un elemento. BlockingQueue no acepta un valor nulo. Si intentamos poner en cola el elemento nulo, arroja NullPointerException.
Java proporciona varias implementaciones de BlockingQueue, como LinkedBlockingQueue , ArrayBlockingQueue , PriorityBlockingQueue , SynchronousQueue , etc. Las implementaciones de la interfaz de Java BlockingQueue son seguras para subprocesos. Todos los métodos de BlockingQueue son de naturaleza atómica y usan bloqueos internos u otras formas de control de concurrencia. Java 5 viene con implementaciones de BlockingQueue en el paquete java.util.concurrent
 

Uso de BlockingQueue 
 

Usage of BlockingQueue 

Una BlockingQueue a la que accede un subproceso productor (put) y un subproceso consumidor (take)

La jerarquía de BlockingQueue

Hierarchy of BlockingQueue

Declaración

public interface BlockingQueue<E> extends Queue<E>

Aquí, E es el tipo de elementos almacenados en la Colección.

Clases que implementan BlockingQueue

No podemos proporcionar directamente una instancia de BlockingQueue ya que es una interfaz, por lo que para utilizar la funcionalidad de BlockingQueue, debemos utilizar las clases que la implementan. Además, para usar BlockingQueue en su código, use esta declaración de importación.

import java.util.concurrent.BlockingQueue;
                    (or)
import java.util.concurrent.*;

La clase de implementación de BlockingDeque es LinkedBlockingDeque. Esta clase es la implementación de BlockingDeque y la estructura de datos de lista enlazada. LinkedBlockingDeque se puede limitar opcionalmente mediante un constructor; sin embargo, si la capacidad no se especifica, es Integer.MAX_VALUE de forma predeterminada. Los Nodes se agregan dinámicamente en el momento de la inserción obedeciendo las restricciones de capacidad.

La sintaxis para crear objetos:

BlockingQueue<?> objectName = new LinkedBlockingDeque<?>();   
                         (or)
LinkedBlockingDeque<?> objectName = new LinkedBlockingDeque<?>();

Ejemplo: en el código que se proporciona a continuación, realizamos algunas operaciones básicas en LinkedBlockingDeque, como crear un objeto, agregar elementos, eliminar elementos y usar un iterador para atravesar LinkedBlockingDeque.

Tipos de BlockingQueue

Los BlockingQueue son de dos tipos :

1. Cola ilimitada: la capacidad de la cola de bloqueo se establecerá en Integer.MAX_VALUE. En el caso de una cola de bloqueo ilimitada, la cola nunca se bloqueará porque podría crecer hasta un tamaño muy grande. cuando agrega elementos, su tamaño crece.

Sintaxis:

BlockingQueue blockingQueue = new LinkedBlockingDeque();

2. Cola limitada: el segundo tipo de cola es la cola limitada. En el caso de una cola limitada, puede crear una cola pasando la capacidad de la cola en el constructor de colas:

Sintaxis:

// Creates a Blocking Queue with capacity 5
BlockingQueue blockingQueue = new LinkedBlockingDeque(5);

Para implementar Bounded Semaphore usando BlockingQueue 

Java

// 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 int limit = 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)
    {
    }
}

 
 Ejemplo: 

Java

// 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);
    }
}
Producción: 

queue contains [StarWars, SuperMan, Flash, BatMan, Avengers]
queue contains [Flash, BatMan, Avengers, CaptainAmerica, Thor]

 

Operaciones básicas

1. Agregar elementos

Los elementos se pueden agregar a un LinkedBlockedDeque de diferentes maneras según el tipo de estructura que intentemos usar. El método más común es el método add() mediante el cual podemos agregar elementos al final de la deque. También podemos usar el método addAll() (que es un método de la interfaz Collection) para agregar una colección completa a LinkedBlockingDeque. Si deseamos usar el deque como una cola, podemos usar add() y put().

Java

// 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);
    }
}
Producción

Blocking Queue: [7855642, 35658786, 5278367, 74381793]

2. Elementos de acceso

Se puede acceder a los elementos de LinkedBlockingDeque usando contains(), element(), peek(), poll(). También hay variaciones de estos métodos que se dan en la tabla anterior junto con sus descripciones.

Java

// 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);
    }
}
Producción

The LinkedBlockingDeque, lbdq contains:
[22, 125, 723, 172, 100]
The LinkedBlockingDeque, lbdq contains 22
The head of lbdq: 22

3. Eliminación de elementos

Los elementos se pueden eliminar de un LinkedBlockingDeque mediante remove(). Otros métodos como take() y poll() también se pueden usar para eliminar el primer y el último elemento.

Java

// 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(
            "\nThe LinkedBlockingDeque, lbdq contains:");
        System.out.println(lbdq);
    }
}
Producción

The LinkedBlockingDeque, lbdq contains:
[75, 86, 13, 44, 10]

The LinkedBlockingDeque, lbdq contains:
[75, 13, 10]

4. Iterando a través de los Elementos

Para iterar a través de los elementos de un LinkedBlockingDeque, podemos crear un iterador y usar los métodos de la interfaz Iterable, que es la raíz de Collection Framework de Java, para acceder a los elementos. El método next() de Iterable devuelve el elemento de cualquier colección.

Java

// 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() + " ");
        }       
    }
 
}
Producción

The LinkedBlockingDeque, lbdq contains:
166 246 66 292 98 

Métodos de BlockingQueue

MÉTODO

DESCRIPCIÓN

agregar​(E e) Inserta el elemento especificado en esta cola si es posible hacerlo de inmediato sin infringir las restricciones de capacidad, devolviendo verdadero en caso de éxito y lanzando una IllegalStateException si no hay espacio disponible actualmente.
contiene​(Objeto o) Devuelve verdadero si esta cola contiene el elemento especificado.
drenajeA​(Colección<? super E> c) Elimina todos los elementos disponibles de esta cola y los agrega a la colección dada.
drenajeA​(Colección<? super E> c, int maxElements) Elimina como máximo el número dado de elementos disponibles de esta cola y los agrega a la colección dada.
oferta​(E e) Inserta el elemento especificado en esta cola si es posible hacerlo de inmediato sin violar las restricciones de capacidad, devolviendo verdadero si tiene éxito y falso si no hay espacio disponible actualmente.
oferta​(E e, tiempo de espera largo, unidad TimeUnit) Inserta el elemento especificado en esta cola, esperando hasta el tiempo de espera especificado si es necesario para que haya espacio disponible.
sondeo​(tiempo de espera prolongado, unidad TimeUnit) Recupera y elimina el encabezado de esta cola, esperando hasta el tiempo de espera especificado si es necesario para que un elemento esté disponible.
poner​(E e) Inserta el elemento especificado en esta cola y espera, si es necesario, a que haya espacio disponible.
capacidad restante() Devuelve el número de elementos adicionales que esta cola puede aceptar idealmente (en ausencia de restricciones de memoria o recursos) sin bloqueo, o Integer.MAX_VALUE si no hay un límite intrínseco.
eliminar​(Objeto o) Elimina una sola instancia del elemento especificado de esta cola, si está presente.
tomar() Recupera y elimina el encabezado de esta cola, esperando si es necesario hasta que un elemento esté disponible.

Métodos declarados en la interfaz java.util.Collection

MÉTODO

DESCRIPCIÓN

addAll​(Colección<? extiende E> c) Agrega todos los elementos de la colección especificada a esta colección (operación opcional).
clear() Elimina todos los elementos de esta colección (operación opcional).
contieneTodo​(Colección<?> c) Devuelve verdadero si esta colección contiene todos los elementos de la colección especificada.
es igual a​(Objeto o) Compara el objeto especificado con esta colección para la igualdad.
código hash() Devuelve el valor del código hash para esta colección.
esta vacio() Devuelve verdadero si esta colección no contiene elementos.
iterador() Devuelve un iterador sobre los elementos de esta colección.
flujoParalelo() Devuelve un Stream posiblemente paralelo con esta colección como fuente.
removeAll​(Colección<?> c) Elimina todos los elementos de esta colección que también están contenidos en la colección especificada (operación opcional).
removeIf​(predicado<? filtro super E>) Elimina todos los elementos de esta colección que satisfacen el predicado dado.
retenerTodo​(Colección<?> c) Retiene solo los elementos de esta colección que están contenidos en la colección especificada (operación opcional).
Talla() Devuelve el número de elementos de esta colección.
divisor() Crea un Spliterator sobre los elementos de esta colección.
corriente() Devuelve un Stream secuencial con esta colección como fuente.
aArray() Devuelve una array que contiene todos los elementos de esta colección.
toArray​(IntFunction<T[]> generador) Devuelve una array que contiene todos los elementos de esta colección, utilizando la función de generador proporcionada para asignar la array devuelta.
a la Array​(T[] a) Devuelve una array que contiene todos los elementos de esta colección; el tipo de tiempo de ejecución de la array devuelta es el de la array especificada.

Métodos declarados en la interfaz java.lang.Iterable

MÉTODO

DESCRIPCIÓN

forEach​(Consumidor<? super T> acción) Realiza la acción dada para cada elemento del iterable hasta que se hayan procesado todos los elementos o la acción genere una excepción.

Métodos declarados en la interfaz java.util.Queue

MÉTODO

DESCRIPCIÓN

elemento() Recupera, pero no elimina, el encabezado de esta cola.
ojeada() Recupera, pero no elimina, el encabezado de esta cola o devuelve un valor nulo si esta cola está vacía.
encuesta() Recupera y elimina el encabezado de esta cola, o devuelve un valor nulo si esta cola está vacía.
retirar() Recupera y elimina el encabezado de esta cola.

El comportamiento de los métodos BlockingQueue

Los siguientes son los métodos proporcionados por BlockingQueue para las operaciones de inserción, eliminación y examen en la cola. Cada uno de los cuatro conjuntos de métodos se comporta de manera diferente si la operación solicitada no se cumple inmediatamente.

  • Lanza una excepción: se lanzará una excepción si la operación solicitada no se cumple de inmediato.
  • Valor especial: se devuelve un valor especial si la operación no se cumple inmediatamente.
  • Bloqueos: la llamada al método se bloquea si la operación intentada no se satisface inmediatamente y espera hasta que se ejecuta.
  • Tiempos de espera: se devuelve un valor especial que indica si la operación tuvo éxito o no. Si la operación solicitada no es posible de inmediato, la llamada al método se bloquea hasta que lo es, pero no espera más que el tiempo de espera dado.
Operación Lanza una excepción Valor especial bloques Se acabó el tiempo
Insertar  añadir (e)  oferta  poner (e)  oferta(e, tiempo, unidad)
Remover retirar()  encuesta()  tomar()  encuesta (tiempo, unidad)
Examinar  elemento()  ojeada()  no aplica  no aplica

Referencia: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/BlockingQueue.html

Publicación traducida automáticamente

Artículo escrito por Rajput-Ji y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *