Callable oder Runnable mit FutureTask ummanteln

Die Klasse java.util.concurrent.FutureTask implementiert Future, Runnable und RunnableFuture und wird intern von der Java-Bibliothek verwendet, wenn wir mit submit(…) etwas beim ExecutorService absetzen. Auch wir können den Typ direkt als Wrapper um ein Callable oder Runnable nutzen, denn es gibt praktische Callback-Methoden, die wir überschreiben können, etwa done(), wenn eine Berechung fertig ist.

Dazu ein Beispiel: Ein Callable liefert den Namen des Benutzers. Ein FutureTask legt sich um dieses Callable und bekommt mit, wann das Callable fertig ist und modifiziert dann den Benutzernamen und gibt weiterhin eine Meldung aus.

Callable<String> username = () -> System.getProperty( "user.name" );

FutureTask<String> wrappedUsername = new FutureTask<>( username ) {

  @Override

  protected void done() {

    try {

      System.out.printf( "done: isDone=%s, isCancelled=%s%n", isDone(), isCancelled() );

      System.out.println( "done: get=" + get() );

    }

    catch ( InterruptedException | ExecutionException e ) { /* Ignore */ }

  }

  @Override

  protected void set( String v ) {

    System.out.println( "set: " + v );

    super.set( v.toUpperCase() );

  }

};

ExecutorService scheduler = Executors.newCachedThreadPool();

scheduler.submit( wrappedUsername );

System.out.println( "main: " + wrappedUsername.get() );

scheduler.shutdown();

Wichtig in der Nutzung ist, nicht die Rückgabe vom submit(…) auszuwerten, was wir normalerweise machen, sondern das übergebene FutureTask zu erfragen.

Die Ausgaben vom Programm sind oft ein wenig durcheinander:

set: Christian
done: isDone=true, isCancelled=false
done: get=CHRISTIAN
main: CHRISTIAN

Die Reihenfolge in den Aufrufen ist immer so: Der FutureTask stellt die Fertigstellung vom Callable fest und ruft set(…) auf. Anschließend done().

Ähnliche Beiträge

Veröffentlicht in Insel

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert