Colas de tareas en Java: desde mecanismos integrados hasta frameworks modernos
\n\nLas colas de tareas (Task Queues) son un patrón fundamental para construir aplicaciones Java escalables y tolerantes a fallos. Permiten separar la lógica de negocio de la gestión de hilos, equilibrar la carga y procesar tareas de forma asíncrona. En este artículo analizaremos las principales implementaciones de colas de tareas en Java, su arquitectura, ejemplos de código y escenarios de uso.
\n\n1. Mecanismos integrados: ThreadPoolExecutor y BlockingQueue
\n\nLa biblioteca estándar de Java (java.util.concurrent) ofrece un potente conjunto de herramientas para trabajar con colas de tareas. La base es la clase ThreadPoolExecutor, que gestiona un grupo de hilos y utiliza una cola para almacenar las tareas en espera.
Ejemplo básico:
\nimport java.util.concurrent.*;\n\npublic class TaskQueueExample {\n public static void main(String[] args) {\n // Creamos un grupo de hilos: corePoolSize=2, maxPoolSize=4, cola de 100 tareas\n ThreadPoolExecutor executor = new ThreadPoolExecutor(\n 2, // corePoolSize\n 4, // maximumPoolSize\n 60, // keepAliveTime\n TimeUnit.SECONDS,\n new LinkedBlockingQueue<>(100) // cola de tareas\n );\n\n // Enviamos tareas\n for (int i = 0; i < 10; i++) {\n final int taskId = i;\n executor.submit(() -> {\n System.out.println("Tarea " + taskId + " ejecutada por el hilo " + \n Thread.currentThread().getName());\n try {\n Thread.sleep(1000);\n } catch (InterruptedException e) {\n Thread.currentThread().interrupt();\n }\n });\n }\n\n // Finalización correcta\n executor.shutdown();\n }\n}\n\nTipos de colas para ThreadPoolExecutor:
\n- \n
LinkedBlockingQueue— cola ilimitada basada en lista enlazada. Adecuada para sistemas donde la cantidad de tareas no se conoce de antemano. \n ArrayBlockingQueue— cola limitada basada en array. Permite controlar el número máximo de tareas en espera. \n SynchronousQueue— cola sin capacidad: cadaput()espera untake(). Se usa para pasar tareas directamente a los hilos. \n PriorityBlockingQueue— cola con prioridad. Las tareas se ordenan según un comparador definido. \n
2. Arquitectura Productor-Consumidor basada en colas
\n\nEl patrón clásico Productor-Consumidor se implementa fácilmente con BlockingQueue. Los productores colocan tareas en la cola, y los consumidores las extraen para procesarlas.
Ejemplo de implementación:
\nimport java.util.concurrent.*;\n\npublic class ProducerConsumerExample {\n private static final BlockingQueue<String> queue = new LinkedBlockingQueue<>(5);\n\n static class Producer implements Runnable {\n @Override\n public void run() {\n try {\n for (int i = 0; i < 10; i++) {\n String task = "Tarea-" + i;\n queue.put(task); // se bloquea si la cola está llena\n System.out.println("Producida: " + task);\n Thread.sleep(100);\n }\n } catch (InterruptedException e) {\n Thread.currentThread().interrupt();\n }\n }\n }\n\n static class Consumer implements Runnable {\n @Override\n public void run() {\n try {\n while (true) {\n String task = queue.take(); // se bloquea si la cola está vacía\n System.out.printl