¿Qué es java.util.concurrent.LinkedBlockingQueue y cómo funciona en Java?

| Última modificación: 17 de enero de 2025 | Tiempo de Lectura: 3 minutos

Algunos de nuestros reconocimientos:

Premios KeepCoding

En Java, quienes logran gestionar tareas concurrentes sin tener complicaciones, se merecen un trofeo. Para lograrlo, yo tuve que buscar muchas alternativas, hasta que finalmente di con java.util.concurrent.LinkedBlockingQueue. Gracias a esta herramienta dejé de estar tan confundido con los hilos, las colas y la concurrencia. Voy a explicarte detalladamente, como nunca nadie te ha explicado, cómo funciona esta clase y por qué es tan apetecida para trabajar con datos en escenarios multihilo.

java.util.concurrent.LinkedBlockingQueue qué es

¿Qué es java.util.concurrent.LinkedBlockingQueue?

Para explicártelo tengo que dividir a la mitad el nombre de esta clase. Primero, LinkedBlockingQueue es como una fila de personas (elementos de datos) que están esperando para entrar a cine y cada una está ordenada detrás de otra, esperando su turno para entrar (o sea para ser procesada).

Segundo, java.util.concurrent sería el conjunto de reglas y herramientas del cine para gestionar la fila y las taquillas, así:

  • Señales para que las taquillas sepan cuándo hay gente esperando o cuándo la fila está vacía.
  • El diseño de la fila (LinkedBlockingQueue) para que sea accesible desde varias taquillas.
  • Mecanismos para que las taquillas se coordinen y no se pisen entre sí.

Piensa en una tienda online, cada orden de compra puede ser un elemento en la fila, y los hilos serían los encargados de procesar cada orden, uno por uno.

Entonces, java.util.concurrent.LinkedBlockingQueue es una implementación de una cola bloqueante basada en nodos enlazados, que puede ser acotada o no acotada, dependiendo de si le defines un tamaño máximo al instanciarla.

Características principales

  1. FIFO (First In, First Out): Los elementos se procesan en el orden en que se insertan.
  2. Bloqueo en límites: Si la cola está llena, los hilos que intenten añadir elementos se bloquearán hasta que haya espacio.
  3. Capacidad ajustable: Puedes definir un límite al crearlo o dejarlo sin límite, en cuyo caso la capacidad máxima será Integer.MAX_VALUE.

Jerarquía de LinkedBlockingQueue

No puedes olvidar que la clase LinkedBlockingQueue extiende AbstractQueue e implementa múltiples interfaces, como BlockingQueue, Collection e Iterable, por eso es versátil y compatible con el resto de las colecciones de Java.

¿Cómo funciona java.util.concurrent.LinkedBlockingQueue? Ejemplos prácticos

Creación de una LinkedBlockingQueue

Para empezar, importa la clase desde java.util.concurrent.LinkedBlockingQueue. Mira que puedes crearla de tres formas diferentes:

Sin especificar capacidad

LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>();

Con una capacidad fija

LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>(10);

A partir de una colección existente

List<String> items = List.of("A", "B", "C");
LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>(items);

Operaciones comunes de java.util.concurrent.LinkedBlockingQueue

Añadir elementos

Puedes usar el método add() o put(). La diferencia principal es que put() bloqueará el hilo si la cola está llena, mientras que add() lanzará una excepción.

queue.put("Elemento 1");
queue.put("Elemento 2");
System.out.println(queue); // Salida: [Elemento 1, Elemento 2]

Obtener y eliminar elementos

El método take() es muy útil porque bloquea hasta que haya elementos disponibles.

String item = queue.take();
System.out.println("Elemento extraído: " + item);

Consultar elementos sin eliminarlos

Si solo quieres ver qué hay en la cabeza de la cola, utiliza peek().

String head = queue.peek();
System.out.println("Elemento al frente: " + head);

Ejemplo práctico avanzado: Procesador de tareas

Ahora sí quiero mostrarte un caso realista, para que tengas más claro cómo llevar este aprendizaje a la cotidianidad. Imagina que tienes múltiples productores generando datos y un consumidor procesándolos.

import java.util.concurrent.LinkedBlockingQueue;

public class TareasConcurrentes {
public static void main(String[] args) throws InterruptedException {
LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>(5);

// Productor
Thread producer = new Thread(() -> {
try {
for (int i = 1; i <= 10; i++) {
queue.put("Tarea " + i);
System.out.println("Producida: Tarea " + i);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});

// Consumidor
Thread consumer = new Thread(() -> {
try {
while (true) {
String task = queue.take();
System.out.println("Procesada: " + task);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});

producer.start();
consumer.start();

producer.join();
consumer.interrupt(); // Detenemos al consumidor después de procesar
}
}

En este ejemplo, el productor genera 10 tareas, mientras el consumidor las procesa. La cola garantiza que las tareas no se pierdan y se manejen en orden.

Ventajas de usar LinkedBlockingQueue

  • Facilidad para gestionar concurrencia: Sin necesidad de sincronizar manualmente los hilos.
  • Versatilidad: Útil para patrones de diseño como productor-consumidor.
  • Escalabilidad: Las colas enlazadas tienen mayor rendimiento que las basadas en arrays en aplicaciones concurrentes.

No te mentí cuando te dije que java.util.concurrent.LinkedBlockingQueue te abre puertas a desarrollar aplicaciones más completas y eficientes. Si quieres profundizar más en estas herramientas y convertirte en un desarrollador completo, el Bootcamp de Java Full Stack de KeepCoding es para ti. No solo aprenderás Java, sino también todo lo necesario para destacar en el sector IT. ¡Apúntate y da el salto hoy mismo!

Posts más leídos