Clases Avanzadas Callable Future Y Completablefuture
Clases Avanzadas: Callable, Future y CompletableFuture
En el desarrollo de aplicaciones concurrentes en Java, las clases Callable, Future y CompletableFuture proporcionan herramientas avanzadas para manejar tareas asincrónicas, controlar su ejecución y gestionar sus resultados. Este documento explora cómo funcionan estas clases, sus diferencias y cómo utilizarlas de manera efectiva.
1. Introducción a Callable
Callable es una interfaz funcional en Java que representa una tarea que devuelve un resultado y puede lanzar excepciones comprobadas. Es similar a Runnable, pero con las siguientes diferencias clave:
- Devuelve un resultado de tipo genérico
T. - Puede lanzar excepciones comprobadas.
Definición de la interfaz Callable
@FunctionalInterface
public interface Callable<V> {
V call() throws Exception;
}
Ejemplo de uso de Callable
import java.util.concurrent.Callable;
public class EjemploCallable {
public static void main(String[] args) throws Exception {
Callable<String> tarea = () -> {
Thread.sleep(1000); // Simula trabajo
return "Resultado de la tarea";
};
String resultado = tarea.call();
System.out.println(resultado);
}
}
2. Introducción a Future
Future es una interfaz que representa el resultado de una tarea asincrónica. Se utiliza junto con ExecutorService para manejar tareas concurrentes.
Principales métodos de Future
get(): Bloquea hasta que el resultado está disponible.get(long timeout, TimeUnit unit): Bloquea hasta que el resultado está disponible o el tiempo de espera expira.cancel(boolean mayInterruptIfRunning): Intenta cancelar la tarea.isDone(): Verifica si la tarea ha terminado.isCancelled(): Verifica si la tarea fue cancelada.
Ejemplo de uso de Future
import java.util.concurrent.*;
public class EjemploFuture {
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<String> tarea = () -> {
Thread.sleep(2000); // Simula trabajo
return "Resultado de Future";
};
Future<String> future = executor.submit(tarea);
try {
System.out.println("Esperando el resultado...");
String resultado = future.get();
System.out.println("Resultado: " + resultado);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} finally {
executor.shutdown();
}
}
}
3. Introducción a CompletableFuture
CompletableFuture es una implementación avanzada de Future que permite construir flujos de trabajo asincrónicos y reactivos. Proporciona una API rica para manejar tareas sin necesidad de bloquear hilos.
Características clave de CompletableFuture
- Encadenamiento de tareas: Permite encadenar tareas usando métodos como
thenApply,thenAcceptythenRun. - Ejecución asincrónica: Usa métodos como
supplyAsyncyrunAsyncpara ejecutar tareas en pools de hilos. - Manejo de errores: Proporciona métodos como
exceptionallyyhandlepara gestionar excepciones.
Principales métodos de CompletableFuture
supplyAsync(Supplier<T>): Ejecuta una tarea que devuelve un resultado.runAsync(Runnable): Ejecuta una tarea que no devuelve resultado.thenApply(Function<T, R>): Transforma el resultado de una tarea.thenAccept(Consumer<T>): Consume el resultado de una tarea.exceptionally(Function<Throwable, T>): Maneja excepciones.
Ejemplo de uso de CompletableFuture
import java.util.concurrent.*;
public class EjemploCompletableFuture {
public static void main(String[] args) {
CompletableFuture<String> futuro = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000); // Simula trabajo
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
return "Resultado de CompletableFuture";
});
futuro.thenApply(resultado -> {
System.out.println("Procesando resultado: " + resultado);
return resultado.toUpperCase();
}).thenAccept(resultadoFinal -> {
System.out.println("Resultado final: " + resultadoFinal);
}).exceptionally(e -> {
System.out.println("Error: " + e.getMessage());
return null;
});
// Esperar la terminación de las tareas
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
4. Diferencias clave entre Future y CompletableFuture
| Característica | Future | CompletableFuture |
|---|---|---|
| Bloqueo | Bloquea con get() |
No bloquea, usa callbacks |
| Encadenamiento | No soportado | Soportado |
| Manejo de errores | Manual | Incorporado |
| Ejecución asincrónica | Limitada | Totalmente soportada |
| API rica | No | Sí |
5. Buenas Prácticas
- Usar
CompletableFuturepara tareas complejas: Es ideal para flujos de trabajo reactivos y asincrónicos. - Liberar recursos: Siempre cierra los pools de hilos con
shutdown(). - Manejar excepciones: Usa
exceptionallyohandlepara evitar errores no controlados. - Evitar bloqueos innecesarios: Prefiere el encadenamiento sobre el uso de
get().
6. Conclusión
Callable, Future y CompletableFuture son herramientas esenciales para manejar tareas concurrentes en Java. Mientras que Callable y Future ofrecen una base para la concurrencia, CompletableFuture permite construir aplicaciones más avanzadas, eficientes y reactivas. Dominar estas clases es fundamental para desarrollar aplicaciones modernas y escalables.