Future y gestión de errores
Use Future.get con tiempos de espera, gestione ExecutionException y cancele tareas en ejecución.
Future y gestión de errores es una lección gratuita de Java Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Java Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Java Academy incluye 4 lecciones en total.
¿Qué es Future?
Un Future<V> representa el resultado pendiente de un cálculo asíncrono. Proporciona métodos para comprobar si ha terminado, esperar el resultado y gestionar errores.
import java.util.concurrent.*;
ExecutorService pool = Executors.newFixedThreadPool(2);
Future<Integer> future = pool.submit(() -> {
Thread.sleep(1000);
return 42;
});
System.out.println("Is done? " + future.isDone()); // false
Integer result = future.get(); // blocks
System.out.println("Result: " + result); // 42
pool.shutdown();future.get() con tiempo de espera
Prefiera siempre la variante con tiempo de espera para evitar que la ejecución se bloquee indefinidamente:
try {
Integer result = future.get(5, TimeUnit.SECONDS);
System.out.println(result);
} catch (TimeoutException e) {
System.out.println("Timed out");
future.cancel(true); // interrupt the task
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
System.out.println("Task threw: " + e.getCause());
}ExecutionException
Si la tarea lanza una excepción, future.get() la envuelve en ExecutionException. Extraiga la excepción original con getCause():
Future<String> failing = pool.submit(() -> {
throw new IllegalArgumentException("bad input");
});
try {
failing.get();
} catch (ExecutionException e) {
Throwable cause = e.getCause();
System.out.println(cause.getClass().getSimpleName()); // IllegalArgumentException
System.out.println(cause.getMessage()); // bad input
}Cancelar un Future
cancel(mayInterruptIfRunning) intenta cancelar la tarea. Devuelve true si tiene éxito. Si mayInterruptIfRunning es true, se envía una interrupción al hilo en ejecución.
Future<String> f = pool.submit(() -> {
try {
Thread.sleep(10_000); // long task
return "done";
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return "interrupted";
}
});
boolean cancelled = f.cancel(true); // send interrupt
System.out.println("Cancelled: " + cancelled); // true
System.out.println("Is cancelled: " + f.isCancelled()); // trueisCancelled frente a isDone
isDone() devuelve true si la tarea terminó normalmente, lanzó una excepción o fue cancelada. isCancelled() devuelve true únicamente si fue cancelada.
// After cancel:
System.out.println(f.isDone()); // true
System.out.println(f.isCancelled()); // true
// After normal completion:
Future<Integer> done = pool.submit(() -> 5);
done.get(); // wait
System.out.println(done.isDone()); // true
System.out.println(done.isCancelled()); // falseCompletionService para obtener el primer resultado disponible
ExecutorCompletionService envuelve un grupo y proporciona un método take() para recuperar el siguiente Future completado, en orden de finalización y no de envío:
ExecutorCompletionService<Integer> cs =
new ExecutorCompletionService<>(pool);
for (int i = 0; i < 5; i++) {
final int delay = 5 - i; // submit fastest last
cs.submit(() -> { Thread.sleep(delay * 100); return delay; });
}
for (int i = 0; i < 5; i++) {
Future<Integer> f = cs.take(); // next completed
System.out.println(f.get());
}Gestionar varios Future de forma segura
Al recopilar resultados de muchos Future, recórralos y gestione las excepciones de cada uno:
List<Future<String>> futures = new ArrayList<>();
for (int i = 0; i < 5; i++) {
final int id = i;
futures.add(pool.submit(() ->
id % 2 == 0 ? "ok_" + id : (() -> { throw new RuntimeException("fail_"+id); }).get()
));
}
for (Future<String> f : futures) {
try {
System.out.println(f.get());
} catch (ExecutionException e) {
System.out.println("Error: " + e.getCause().getMessage());
}
}Future.get() después de apagar el grupo
Enviar tareas después de shutdown() lanza RejectedExecutionException. Sin embargo, los Future enviados ANTES del apagado todavía se pueden recuperar después de este:
ExecutorService pool2 = Executors.newFixedThreadPool(2);
Future<Integer> f = pool2.submit(() -> 99);
pool2.shutdown(); // no new tasks
// Still valid — task was submitted before shutdown:
System.out.println(f.get()); // 99
try {
pool2.submit(() -> 0); // throws!
} catch (RejectedExecutionException e) {
System.out.println("Pool shut down");
}FutureTask: Future manual
FutureTask<V> implementa tanto Runnable como Future<V>, lo que resulta útil cuando necesita un Future sin ExecutorService:
FutureTask<String> task = new FutureTask<>(() -> "computed");
new Thread(task).start(); // run in any thread
System.out.println(task.get()); // computedPatrón de reintento con Future
Implemente una lógica de reintento sencilla alrededor de future.get():
Future<String> future = pool.submit(() -> {
if (Math.random() < 0.7) throw new RuntimeException("transient error");
return "success";
});
for (int attempt = 0; attempt < 3; attempt++) {
try {
System.out.println(future.get());
break;
} catch (ExecutionException e) {
System.out.println("Attempt " + (attempt+1) + " failed");
if (attempt == 2) throw e;
future = pool.submit(() -> "retry"); // resubmit
}
}Limitaciones de Future
java.util.concurrent.Future tiene varias limitaciones:
- No admite callbacks: debe bloquearse con get()
- No permite encadenar transformaciones
- No permite combinar varios Future
Use CompletableFuture (en el curso siguiente) para realizar composiciones reactivas y sin bloqueo.
Comprobación rápida
Una tarea lanza una excepción. Cuando llama a future.get(), ¿qué excepción se lanza?
Repaso: Future y gestión de errores
Conceptos clave:
- future.get() bloquea; use siempre la variante con tiempo de espera
- ExecutionException envuelve las excepciones de la tarea; extráigalas con getCause()
- cancel(true) envía una interrupción; use isDone/isCancelled para consultar el estado
- ExecutorCompletionService.take() recupera los Future en orden de finalización
- FutureTask implementa tanto Runnable como Future
Preguntas frecuentes
¿La lección «Future y gestión de errores» es gratis?
Sí — el texto completo de «Future y gestión de errores» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Java Academy, actualiza a CoddyKit PRO. El curso de Java Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Future y gestión de errores»?
Use Future.get con tiempos de espera, gestione ExecutionException y cancele tareas en ejecución. Practicas Java Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Java Academy?
No se requiere experiencia previa. Java Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.
¿Cuánto tiempo toma la lección «Future y gestión de errores»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Java Academy?
Sí. Cada lección de Java Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- ExecutorService y tipos de grupos de hilos
- Envío de tareas: Runnable frente a Callable
- Future y gestión de errores
- ScheduledExecutorService para tareas recurrentes