Concurrencia de Java: futuros y exigibles

El objeto java.util.concurrent.Callable puede devolver el resultado calculado realizado por un hilo en contraste con la interfaz ejecutable que solo puede ejecutar el hilo. El objeto invocable devuelve el objeto Future que proporciona métodos para monitorear el progreso de una tarea que está siendo ejecutada por un hilo. El objeto Future se puede usar para verificar el estado de un invocable y luego recuperar el resultado del invocable una vez que el hilo está terminado. También proporciona la funcionalidad de tiempo de espera.

Sintaxis

//submit the callable using ThreadExecutor
//and get the result as a Future object
Future<Long> result10 = executor.submit(new FactorialService(10));
 
//get the result using get method of the Future object
//get method waits till the thread execution and then return the result of the execution.
Long factorial10 = result10.get();

Ejemplo

El siguiente programa TestThread muestra el uso de Futures y Callables en un entorno basado en subprocesos.

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class TestThread {

   public static void main(final String[] arguments) throws InterruptedException,
      ExecutionException {

      ExecutorService executor = Executors.newSingleThreadExecutor();

      System.out.println("Factorial Service called for 10!");
      Future<Long> result10 = executor.submit(new FactorialService(10));

      System.out.println("Factorial Service called for 20!");
      Future<Long> result20 = executor.submit(new FactorialService(20));

      Long factorial10 = result10.get();
      System.out.println("10! = " + factorial10);

      Long factorial20 = result20.get();
      System.out.println("20! = " + factorial20);

      executor.shutdown();
   }  

   static class FactorialService implements Callable<Long> {
      private int number;

      public FactorialService(int number) {
         this.number = number;
      }

      @Override
      public Long call() throws Exception {
         return factorial();
      }

      private Long factorial() throws InterruptedException {
         long result = 1; 
         
         while (number != 0) { 
            result = number * result; 
            number--; 
            Thread.sleep(100); 
         }
         return result;	
      }
   }
}

Esto producirá el siguiente resultado.

Salida

Factorial Service called for 10!
Factorial Service called for 20!
10! = 3628800
20! = 2432902008176640000