Programación asíncrona en Java: guía completa en la práctica

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

Introducción a la programación asíncrona en Java



Las aplicaciones modernas requieren alto rendimiento y capacidad de respuesta. Los usuarios no están dispuestos a esperar mientras la aplicación procesa una solicitud a la base de datos o realiza una llamada de red. Aquí es donde la programación asíncrona en Java viene al rescate: un enfoque que permite no bloquear el hilo principal de ejecución mientras se espera la finalización de operaciones largas.



A diferencia del multihilo tradicional, donde gestionas explícitamente los hilos, la programación asíncrona ofrece abstracciones de más alto nivel. En lugar de crear nuevos hilos manualmente, utilizas CompletableFuture, ExecutorService y otras herramientas proporcionadas por Java Concurrency API.



En este artículo, analizaremos los conceptos clave de la programación asíncrona en Java con ejemplos prácticos. Aprenderás cómo manejar tareas asíncronas, combinarlas en cadenas y trabajar eficientemente con el multihilo.



Herramientas principales de la programación asíncrona en Java



1. CompletableFuture — la base de la asincronía



CompletableFuture es una clase que apareció en Java 8 y proporciona una potente API para la programación asíncrona. Permite crear tareas asíncronas, combinarlas, manejar errores y transformar resultados.



Veamos un ejemplo simple de creación y ejecución de una tarea asíncrona:



import java.util.concurrent.CompletableFuture;import java.util.concurrent.ExecutionException;

public class AsyncExample { public static void main(String[] args) throws ExecutionException, InterruptedException { // Creamos una tarea asíncrona CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { try { Thread.sleep(1000); // Simulación de una operación larga } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return "Resultado de la operación asíncrona"; });

// Añadimos un manejador de finalización future.thenAccept(result -> System.out.println("Resultado recibido: " + result));

// El hilo principal continúa su trabajo System.out.println("El hilo principal continúa la ejecución");

// Esperamos la finalización (solo para demostración) future.get(); }}


Observa que supplyAsync() por defecto utiliza ForkJoinPool.commonPool(). Este es un pool de hilos optimizado para tareas paralelas.



2. ExecutorService — gestión del pool de hilos



Para un control más preciso sobre la ejecución de tareas asíncronas, utiliza ExecutorService. Esto permite establecer la cantidad de hilos, su comportamiento y la estrategia de procesamiento de tareas.



import java.util.concurrent.*;

public class ExecutorServiceExample { public static void main(String[] args) { // Creamos un pool de 4 hilos ExecutorService executor = Executors.newFixedThreadPool(4);

// Creamos un CompletableFuture con un executor personalizado CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> { try { Thread.sleep(2000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return 42; }, executor);

// Procesamiento del resultado future.thenAccept(result -> { System.out.println("Resultado: " + result); executor.shutdown(); // ¡Importante! Cerramos el pool });

System.out.println("El hilo principal no se bloquea"); }}


Importante: Siempre cierra el ExecutorService con shutdown() o shutdownNow() para evitar fugas de recursos.



3. Combinación

Blogs

Book Recommendations