Java Concurrency - Futures und Callables

Das Objekt java.util.concurrent.Callable kann das berechnete Ergebnis eines Threads zurückgeben, im Gegensatz zur ausführbaren Schnittstelle, die nur den Thread ausführen kann. Das Callable-Objekt gibt das Future-Objekt zurück, das Methoden zum Überwachen des Fortschritts einer von einem Thread ausgeführten Aufgabe bereitstellt. Zukünftiges Objekt kann verwendet werden, um den Status eines Callable zu überprüfen und das Ergebnis aus dem Callable abzurufen, sobald der Thread fertig ist. Es bietet auch Timeout-Funktionen.

Syntax

//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();

Beispiel

Das folgende TestThread-Programm zeigt die Verwendung von Futures und Callables in einer threadbasierten Umgebung.

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;	
      }
   }
}

Dies führt zu folgendem Ergebnis.

Ausgabe

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