© Excellent backgrounds/Shutterstock.com
Java Magazin
Kolumne: Java-Trickkiste

CompletableFuture

Diesen Monat behandelt die Kolumne die Klasse CompletableFuture, die seit Java 8 Teil der Standardbibliothek ist. Sie bietet ein API, mit dem man asynchrone Tasks starten, kombinieren und allgemein verwalten kann. Sie ist ein leistungsstarkes Hilfsmittel, besonders, wenn man reaktive Systeme bauen will [1].

Arno Haase


Klassische FuturesDer Aufrufer erhält dann eine Future-Instanz, die als Platzhalter für das Ergebnis dient. Er kann das Ergebnis zu einem beliebigen Zeitpunkt abfragen, indem er get() aufruft. Dieser Aufruf blockiert, bis die asynchrone Berechnung abgeschlossen ist.Listing 1ExecutorService ec = Executors.newCachedThreadPool ();Future gaussian = ec.submit ((Callable) () -> new Random ().nextGaussian ());System.out.println (gaussian.get ());ExecutorService ec = Executors.newCachedThreadPool ();Future gaussian = ec.submit ((Callable) () -> new Random ().nextGaussian ());System.out.println (gaussian.get ());Außerdem bieten Futures keine Unterstützung für Verarbeitungsketten oder Kombinationen von Ergebnissen. Wenn man z. B. parallel eine Reihe von Werten aus der Datenbank nachschlagen will, um sie dann gemeinsam zu verarbeiten und das Ergebnis über einen Web Service weiterzuleiten, braucht man einen synchron blockierenden Steuerungsthread. Zumindest, wenn man mit klassischen Futures arbeitet.CompletableFutures kombinierenZur Illustration erzeugt Listing 2 asynchron eine Million Gauß-verteilte Zufallszahlen, quadriert jede von ihnen, addiert die Ergebnisse auf und gibt das Ergebnis aus. Der aufrufende Thread initialisiert die Verarbeitungskette dabei, ist aber anschließend überhaupt nicht mehr am Ablauf beteiligt.Listing 2final List> squared = new ArrayList (); for (int i=0; i new Random ().nextGaussian ()). thenApplyAsync ((x) -> x*x) );} CompletableFuture result = CompletableFuture.completedFuture (0.0); for (CompletableFuture f: squared) { result = result.thenCombineAsync (f, (f1, f2) -> f1 + f2);} result.thenAcceptAsync (System.out::println); System.out.println ("Warte...");Thread.sleep (5_000);final List> squared = new ArrayList (); for (int i=0; i new Random ().nextGaussian ()). thenApplyAsync ((x) -> x*x) );} CompletableFuture result = CompletableFuture.completedFuture (0.0); for (CompletableFuture f: squared) { result = result.thenCombineAsync (f, (f1, f2) -> f1 + f2);} result.thenAcceptAsync (System.out::println); System.out.println ("Warte...");Thread.sleep (5_000);Auf diesem CompletableFuture wird gleich die Methode thenApplyAsync aufgerufen, um die Zufallszahl...

Java Magazin
Kolumne: Java-Trickkiste

CompletableFuture

Diesen Monat behandelt die Kolumne die Klasse CompletableFuture, die seit Java 8 Teil der Standardbibliothek ist. Sie bietet ein API, mit dem man asynchrone Tasks starten, kombinieren und allgemein verwalten kann. Sie ist ein leistungsstarkes Hilfsmittel, besonders, wenn man reaktive Systeme bauen will [1].

Arno Haase


Klassische FuturesDer Aufrufer erhält dann eine Future-Instanz, die als Platzhalter für das Ergebnis dient. Er kann das Ergebnis zu einem beliebigen Zeitpunkt abfragen, indem er get() aufruft. Dieser Aufruf blockiert, bis die asynchrone Berechnung abgeschlossen ist.Listing 1ExecutorService ec = Executors.newCachedThreadPool ();Future gaussian = ec.submit ((Callable) () -> new Random ().nextGaussian ());System.out.println (gaussian.get ());ExecutorService ec = Executors.newCachedThreadPool ();Future gaussian = ec.submit ((Callable) () -> new Random ().nextGaussian ());System.out.println (gaussian.get ());Außerdem bieten Futures keine Unterstützung für Verarbeitungsketten oder Kombinationen von Ergebnissen. Wenn man z. B. parallel eine Reihe von Werten aus der Datenbank nachschlagen will, um sie dann gemeinsam zu verarbeiten und das Ergebnis über einen Web Service weiterzuleiten, braucht man einen synchron blockierenden Steuerungsthread. Zumindest, wenn man mit klassischen Futures arbeitet.CompletableFutures kombinierenZur Illustration erzeugt Listing 2 asynchron eine Million Gauß-verteilte Zufallszahlen, quadriert jede von ihnen, addiert die Ergebnisse auf und gibt das Ergebnis aus. Der aufrufende Thread initialisiert die Verarbeitungskette dabei, ist aber anschließend überhaupt nicht mehr am Ablauf beteiligt.Listing 2final List> squared = new ArrayList (); for (int i=0; i new Random ().nextGaussian ()). thenApplyAsync ((x) -> x*x) );} CompletableFuture result = CompletableFuture.completedFuture (0.0); for (CompletableFuture f: squared) { result = result.thenCombineAsync (f, (f1, f2) -> f1 + f2);} result.thenAcceptAsync (System.out::println); System.out.println ("Warte...");Thread.sleep (5_000);final List> squared = new ArrayList (); for (int i=0; i new Random ().nextGaussian ()). thenApplyAsync ((x) -> x*x) );} CompletableFuture result = CompletableFuture.completedFuture (0.0); for (CompletableFuture f: squared) { result = result.thenCombineAsync (f, (f1, f2) -> f1 + f2);} result.thenAcceptAsync (System.out::println); System.out.println ("Warte...");Thread.sleep (5_000);Auf diesem CompletableFuture wird gleich die Methode thenApplyAsync aufgerufen, um die Zufallszahl...

Neugierig geworden?


    
Loading...

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang