Colas de tareas en Java: transformando el caos en orden

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Cuando tu código empieza a tartamudear: introducción a las colas y tareas en segundo plano en Java

\n\n

Imagine la situación: inicia un servidor web en Java. Llega una solicitud de un usuario: hay que enviar un correo, generar un informe PDF y actualizar las estadísticas. Si se hace todo de forma síncrona, el usuario esperará 30 segundos. Su café se enfriará y se irá con la competencia. ¿Le suena familiar?

\n\n

En el mundo de las tareas en segundo plano en Java, esto se resuelve de forma elegante: lanzamos la tarea a una cola y devolvemos al usuario un «200 OK». Luego, en segundo plano, nuestro trabajador procesa tranquilamente los correos, PDFs y estadísticas. Sin caos, solo orden.

\n\n

Hoy analizaremos cómo implementar colas de tareas en Java, desde la opción monohilo más simple hasta soluciones industriales con RabbitMQ y Kafka. Aprenderá a dejar de apagar incendios y empezar a diseñar sistemas fiables.

\n\n

¿Para qué sirven las colas? Tres razones que le sorprenderán

\n\n
    \n
  1. Asincronía — el usuario no espera. La velocidad de respuesta del servidor cae de 30 segundos a 5 milisegundos.
  2. \n
  3. Equilibrio de carga — los picos de solicitudes no tumban el servidor. Las tareas se almacenan en la cola y se procesan a medida que se liberan recursos.
  4. \n
  5. Tolerancia a fallos — si un trabajador falla, la tarea permanece en la cola. Otro trabajador la retomará. Los datos no se pierden.
  6. \n
\n\n

En Java existen herramientas integradas (ExecutorService, BlockingQueue) y brokers externos (RabbitMQ, Kafka). La elección depende de la escala. Empecemos por lo pequeño.

\n\n

Cola simple en Java: ExecutorService y BlockingQueue

\n\n

Si no necesita un sistema distribuido, sino simplemente sacar el trabajo pesado a segundo plano, use ThreadPoolExecutor. Es un grupo de hilos integrado que toma tareas de una cola.

\n\n

Ejemplo: grupo de hilos para procesar pedidos

\n\n
import java.util.concurrent.*;\n\npublic class OrderProcessor {\n    private final ExecutorService executor;\n\n    public OrderProcessor(int threadCount) {\n        // Creamos un grupo con un número fijo de hilos\n        this.executor = Executors.newFixedThreadPool(threadCount);\n    }\n\n    public void processOrder(Order order) {\n        executor.submit(() -> {\n            // Trabajo pesado: generar recibo, enviar email, actualizar inventario\n            System.out.println("Procesando pedido: " + order.getId());\n            try {\n                Thread.sleep(2000); // simulación de trabajo\n            } catch (InterruptedException e) {\n                Thread.currentThread().interrupt();\n            }\n            System.out.println("Pedido " + order.getId() + " procesado");\n        });\n    }\n\n    public void shutdown() {\n        executor.shutdown();\n    }\n\n    public static void main(String[] args) {\n        OrderProcessor processor = new OrderProcessor(4);\n        for (int i = 0; i < 10; i++) {\n            processor.processOrder(new Order(i));\n        }\n        processor.shutdown();\n    }\n}\n\nclass Order {\n    private final int id;\n    public Order(int id) { this.id = id; }\n    public int getId() { return id; }\n}
\n\n

¿Qué ocurre aquí? Hemos creado un grupo de 4 hilos. 10 pedidos se procesarán de 4 en 4 en paralelo. La cola de tareas en Java se gestiona internamente en ThreadPoolExecutor — por defecto es una LinkedBlockingQueue. Cuando todos los hilos están ocupados, las tareas esperan su turno.

\n\n

Configuración avanzada: prioridades y tolerancia a fallos

\n\n

¿Y si las tareas son urgentes? Use PriorityBlockingQueue:

\n\n
BlockingQueue<Runnable> priorityQueue = new PriorityBlockingQueue<>(\n    10,\n    Comparator.comparingInt(task -> ((PriorityTask) task).getPriority())\n);\n\nThreadPoolExecutor executor = new ThreadPoolExecutor(\n    2, 4, 60, TimeUnit.SECONDS, priorityQueue\n);
\n\n

Ahora las tareas con prioridad alta

Blogs

Book Recommendations