Verbesserungen der Java 9 CompletableFuture-API

1. Einleitung

Java 9 enthält einige Änderungen an der CompletableFuture- Klasse. Solche Änderungen wurden im Rahmen von JEP 266 eingeführt, um allgemeine Beschwerden und Vorschläge seit seiner Einführung in JDK 8 zu berücksichtigen, insbesondere Unterstützung für Verzögerungen und Zeitüberschreitungen, bessere Unterstützung für Unterklassen und einige nützliche Methoden.

In Bezug auf den Code enthält die API acht neue Methoden und fünf neue statische Methoden. Um solche Ergänzungen zu ermöglichen, wurden ungefähr 1500 von 2400 Codezeilen geändert (gemäß Open JDK).

2. Instanz-API-Ergänzungen

Wie bereits erwähnt, enthält die Instanz-API acht neue Ergänzungen:

  1. Executor defaultExecutor ()
  2. CompletableFuture newIncompleteFuture ()
  3. CompletableFuture copy ()
  4. CompletionStage minimalCompletionStage ()
  5. CompletableFuture completeAsync (Lieferantenlieferant, Executor Executor)
  6. CompletableFuture completeAsync (Lieferant Lieferant)
  7. CompletableFuture orTimeout (lange Zeitüberschreitung, TimeUnit-Einheit)
  8. CompletableFuture completeOnTimeout (T-Wert, lange Zeitüberschreitung, TimeUnit-Einheit)

2.1. Methode defaultExecutor ()

Signatur : Executor defaultExecutor ()

Gibt den Standard- Executor zurück, der für asynchrone Methoden verwendet wird, die keinen Executor angeben .

new CompletableFuture().defaultExecutor()

Dies kann durch Unterklassen überschrieben werden, die einen Executor zurückgeben, der mindestens einen unabhängigen Thread bereitstellt.

2.2. Methode newIncompleteFuture ()

Unterschrift : CompletableFuture newIncompleteFuture ()

Die newIncompleteFuture , auch als "virtueller Konstruktor" bekannt, wird verwendet, um eine neue abschließbare zukünftige Instanz desselben Typs abzurufen .

new CompletableFuture().newIncompleteFuture()

Diese Methode ist besonders nützlich, wenn Sie CompletableFuture in Unterklassen unterteilen , vor allem, weil sie intern in fast allen Methoden verwendet wird, die eine neue CompletionStage zurückgeben , sodass Unterklassen steuern können, welcher Subtyp von solchen Methoden zurückgegeben wird.

2.3. Methodenkopie ()

Unterschrift : CompletableFuture copy ()

Diese Methode gibt eine neue CompletableFuture zurück, die:

  • Wenn dies normal abgeschlossen wird, wird das neue auch normal abgeschlossen
  • Wenn dies ausnahmsweise mit Ausnahme X abgeschlossen wird, wird die neue auch ausnahmsweise mit einer CompletionException mit X als Ursache abgeschlossen
new CompletableFuture().copy()

Diese Methode kann als eine Form des "defensiven Kopierens" nützlich sein, um zu verhindern, dass Clients abgeschlossen werden, und dennoch abhängige Aktionen für eine bestimmte Instanz von CompletableFuture arrangieren können .

2.4. Methode minimalCompletionStage ()

Signatur : CompletionStage minimalCompletionStage ()

Diese Methode gibt eine neue CompletionStage zurück, die sich genauso verhält wie von der Kopiermethode beschrieben. Diese neue Instanz löst jedoch bei jedem Versuch, den aufgelösten Wert abzurufen oder festzulegen, eine UnsupportedOperationException aus .

new CompletableFuture().minimalCompletionStage()

Eine neue CompletableFuture mit allen verfügbaren Methoden kann mithilfe der toCompletableFuture- Methode abgerufen werden, die in der CompletionStage- API verfügbar ist .

2.5. Methoden completeAsync ()

Die Methode completeAsync sollte verwendet werden, um die CompletableFuture asynchron mit dem vom Lieferanten angegebenen Wert abzuschließen .

Unterschriften :

CompletableFuture completeAsync(Supplier supplier, Executor executor) CompletableFuture completeAsync(Supplier supplier)

Der Unterschied zwischen diesen beiden überladenen Methoden besteht in der Existenz des zweiten Arguments, in dem der Executor angegeben werden kann , der die Aufgabe ausführt. Wenn keine angegeben ist, wird der Standard-Executor (von der defaultExecutor- Methode zurückgegeben) verwendet.

2.6. Methoden orTimeout ()

Signatur : CompletableFuture orTimeout (lange Zeitüberschreitung, TimeUnit-Einheit)

new CompletableFuture().orTimeout(1, TimeUnit.SECONDS)

Löst die CompletableFuture ausnahmsweise mit TimeoutException auf , es sei denn, sie wird vor dem angegebenen Timeout abgeschlossen.

2.7. Methode completeOnTimeout ()

Signatur : CompletableFuture completeOnTimeout (T-Wert, lange Zeitüberschreitung, TimeUnit-Einheit)

new CompletableFuture().completeOnTimeout(value, 1, TimeUnit.SECONDS)

Vervollständigt die CompletableFuture normalerweise mit dem angegebenen Wert, es sei denn, sie wird vor dem angegebenen Zeitlimit abgeschlossen.

3. Statische API-Ergänzungen

Einige Dienstprogrammmethoden wurden ebenfalls hinzugefügt. Sie sind:

  1. Executor verzögertExecutor (lange Verzögerung, TimeUnit-Einheit, Executor Executor)
  2. Executor verzögertExecutor (lange Verzögerung, TimeUnit-Einheit)
  3. CompletionStage completedStage(U value)
  4. CompletionStage failedStage(Throwable ex)
  5. CompletableFuture failedFuture(Throwable ex)

3.1. Methods delayedExecutor

Signatures:

Executor delayedExecutor(long delay, TimeUnit unit, Executor executor) Executor delayedExecutor(long delay, TimeUnit unit)

Returns a new Executor that submits a task to the given base executor after the given delay (or no delay if non-positive). Each delay commences upon invocation of the returned executor's execute method. If no executor is specified the default executor (ForkJoinPool.commonPool()) will be used.

3.2. Methods completedStage and failedStage

Signatures:

 CompletionStage completedStage(U value)  CompletionStage failedStage(Throwable ex)

This utility methods return already resolved CompletionStage instances, either completed normally with a value (completedStage) or completed exceptionally (failedStage) with the given exception.

3.3. Method failedFuture

Signature: CompletableFuture failedFuture(Throwable ex)

The failedFuture method adds the ability to specify an already completed exceptionally CompleatebleFuture instance.

4. Example Use Cases

Within this section, one will show some examples on how to use some of the new API.

4.1. Delay

This example will show how to delay the completion of a CompletableFuture with a specific value by one second. That can be achieved by using the completeAsync method together with the delayedExecutor.

CompletableFuture future = new CompletableFuture(); future.completeAsync(() -> input, CompletableFuture.delayedExecutor(1, TimeUnit.SECONDS));

4.2. Complete With Value on Timeout

Another way to achieve a delayed result is to use the completeOnTimeout method. This example defines a CompletableFuture that will be resolved with a given input if it stays unresolved after 1 second.

CompletableFuture future = new CompletableFuture(); future.completeOnTimeout(input, 1, TimeUnit.SECONDS);

4.3. Timeout

Another possibility is timing out which resolves the future exceptionally with TimeoutException. For example, having the CompletableFuture timing out after 1 second given it is not completed before that.

CompletableFuture future = new CompletableFuture(); future.orTimeout(1, TimeUnit.SECONDS);

5. Conclusion

Zusammenfassend lässt sich sagen, dass Java 9 mehrere Ergänzungen zur CompletableFuture- API enthält. Dank des virtuellen Konstruktors newIncompleteFuture kann jetzt die Unterklasse besser unterstützt werden. Es ist möglich, die Kontrolle über die CompletionStage- Instanzen zu übernehmen, die in den meisten CompletionStage- APIs zurückgegeben werden.

Es hat definitiv eine bessere Unterstützung für Verzögerungen und Zeitüberschreitungen, wie zuvor gezeigt. Die hinzugefügten Dienstprogrammmethoden folgen einem sinnvollen Muster und bieten CompletableFuture eine bequeme Möglichkeit, aufgelöste Instanzen anzugeben.

Die in diesem Artikel verwendeten Beispiele finden Sie in unserem GitHub-Repository.