Cómo usar Future

Future es la clase que te permite controlar una tarea previamente enviada a un ExecutorService de Java. Mediante esta clase vas a poder obtener el resultado de procesar en la tarea un Callable, así como detenerla.

Cuando trabajamos con tareas asíncronas en Java, una herramienta fundamental para controlar esas tareas es la clase Future. Al enviar una tarea a un ExecutorService mediante el método submit, obtenemos un objeto Future que nos permite gestionar esa tarea de forma más cómoda y segura. Este objeto nos da la posibilidad de recuperar el resultado final, cancelar la tarea o consultar su estado.

Imaginemos que tenemos un ExecutorService configurado con un solo hilo para facilitar el control. Enviamos tareas que implementan Callable, que es similar a un Runnable pero con la capacidad de devolver un resultado. Por ejemplo, si nuestro Callable devuelve un Integer, el Future que recibimos será de tipo Future<Integer>. Podemos almacenar este Future en una variable para luego interactuar con la tarea.

Una de las funcionalidades más útiles es obtener el resultado de la tarea con el método get(). Este método bloquea el hilo que lo llama hasta que la tarea haya terminado y el resultado esté disponible, funcionando de manera similar a un await en otros lenguajes. Por ejemplo, si tenemos:

Future<Integer> futuro1 = executor.submit(miCallable);
Integer resultado = futuro1.get();
System.out.println("Resultado: " + resultado);

Aquí, el hilo principal esperará hasta que miCallable termine y devuelva un valor, que luego imprimiremos. Es importante manejar las excepciones que get() puede lanzar, como InterruptedException si el hilo es interrumpido mientras espera, o ExecutionException si la tarea terminó con una excepción.

Además, podemos consultar el estado de la tarea con métodos como isDone() para saber si ha finalizado o isCancelled() para verificar si fue cancelada. Esto nos permite evitar bloqueos innecesarios y tomar decisiones según el estado actual.

Si intentamos obtener el resultado con get() en un orden diferente al que se completan las tareas, el hilo se bloqueará hasta que la tarea solicitada termine. Por ejemplo, si tenemos dos tareas y llamamos primero a futuro2.get() cuando futuro1 termina antes, el hilo esperará a que futuro2 finalice, lo que puede afectar el flujo de ejecución.

Existe también el método getNow(), que intenta obtener el resultado sin esperar. Sin embargo, si la tarea aún no ha terminado, lanzará una excepción, por lo que debemos usarlo con precaución.

Otra característica clave es la capacidad de cancelar tareas con el método cancel(boolean mayInterruptIfRunning). Si la tarea aún no ha comenzado, la cancelación siempre tendrá éxito y la tarea no se ejecutará. Pero si la tarea ya está en ejecución, el comportamiento depende del parámetro mayInterruptIfRunning.

Si pasamos false, la tarea seguirá ejecutándose hasta completarse, ya que no se envía ninguna señal para detenerla. En cambio, si pasamos true, se intenta interrumpir la tarea en ejecución enviándole una señal de interrupción. Esto puede provocar que la tarea lance una InterruptedException y se detenga antes de terminar normalmente.

Por ejemplo, si cancelamos una tarea en ejecución con cancel(true), el hilo que ejecuta la tarea recibirá la interrupción y la tarea puede finalizar prematuramente. Pero si usamos cancel(false), la tarea continuará hasta completarse, ignorando la solicitud de cancelación.

Es importante tener en cuenta que si el hilo principal muere sin llamar a shutdown() en el ExecutorService, las tareas en ejecución seguirán corriendo en segundo plano, lo que puede hacer que el programa no termine correctamente. Por eso, siempre debemos asegurarnos de cerrar el ExecutorService cuando ya no lo necesitemos.

En resumen, Future nos ofrece un control muy potente sobre las tareas asíncronas en Java, permitiéndonos obtener resultados, cancelar tareas y consultar su estado de forma sencilla y segura. Este mecanismo se asemeja bastante al concepto de promesas en otros lenguajes, facilitando la programación concurrente y asíncrona.

Lista de reproducción
  1. 1
    ¿Qué es la concurrencia?
    8 minutos
  2. 2
    ¿Qué es un hilo?
    5 minutos
  3. 3
    Crear un hilo en Java
    10 minutos
  4. 4
    Interrupción de hilos
    10 minutos
  5. 5
    Cómo usar Thread.join
    14 minutos
  6. 6
    Corrupción de memoria
    8 minutos
  7. 7
    Monitores y synchronized
    10 minutos
  8. 8
    Bloque synchronized
    12 minutos
  9. 9
    Preguntas típicas sobre synchronized en Java
    8 minutos
  10. 10
    Interbloqueos, synchronized y el problema de la cena de los filósofos
    13 minutos
  11. 11
    Introducción a Executor en Java
    11 minutos
  12. 12
    Introducción al uso de ExecutorService en Java
    14 minutos
  13. 13
    Introducción a Thread Pools en Java
    10 minutos
  14. 14
    Cómo crear Thread Pools en Java
    11 minutos
  15. 15
    ¿Cómo funcionan wait() y notify()?
    10 minutos
  16. 16
    Ejemplo de wait() y notify() en Java
    9 minutos
  17. 17
    La palabra clave volatile
    8 minutos
  18. 18
    Cómo usar Future
    8 minutos
  19. 19
    Variables atómicas
    7 minutos