Améliorations de l’API Java 9 CompletableFuture

Améliorations de l'API Java 9 CompletableFuture

1. introduction

Java 9 apporte quelques modifications à la classeCompletableFuture. De tels changements ont été introduits dans le cadre deJEP 266 afin de répondre aux plaintes et suggestions courantes depuis son introduction dans JDK 8, plus spécifiquement, la prise en charge des retards et des délais d'expiration, une meilleure prise en charge des sous-classes et quelques méthodes utilitaires.

En termes de code, l'API propose huit nouvelles méthodes et cinq nouvelles méthodes statiques. Pour permettre de tels ajouts, environ 1500 lignes de code sur 2400 ont été modifiées (selon Open JDK).

2. Ajouts d'API d'instance

Comme mentionné, l’API d’instance contient huit nouveaux ajouts, à savoir:

  1. Executor defaultExecutor ()

  2. CompletableFuture nouveauIncompleteFuture ()

  3. Copie CompletableFuture ()

  4. CompletionStage minimalCompletionStage ()

  5. CompletableFuture completeAsync (Supplier fournisseur, exécuteur exécuteur)

  6. CompletableFuture completeAsync (Supplier fournisseur)

  7. CompletableFuture ouTimeout (long timeout, unité TimeUnit)

  8. CompletableFuture completeOnTimeout (valeur T, long timeout, unité TimeUnit)

2.1. MéthodedefaultExecutor()

Signature:Executor defaultExecutor()

Renvoie lesExecutor par défaut utilisés pour les méthodes asynchrones qui ne spécifient pas deExecutor.

new CompletableFuture().defaultExecutor()

Cela peut être annulé par les sous-classes renvoyant un exécuteur fournissant au moins un thread indépendant.

2.2. MéthodenewIncompleteFuture()

Signature:CompletableFuture<U> newIncompleteFuture()

LenewIncompleteFuture, également connu sous le nom de «constructeur virtuel», est utilisé pour obtenir une nouvelle instance future complétable du même type.

new CompletableFuture().newIncompleteFuture()

Cette méthode est particulièrement utile lors du sous-classement deCompletableFuture, principalement parce qu'elle est utilisée en interne dans presque toutes les méthodes retournant un nouveauCompletionStage, permettant aux sous-classes de contrôler quel sous-type est retourné par ces méthodes.

2.3. Méthodecopy()

Signature:CompletableFuture<T> copy()

Cette méthode renvoie un nouveauCompletableFuture qui:

  • Lorsque cela se termine normalement, le nouveau se termine normalement aussi

  • Lorsque cela se termine exceptionnellement avec l'exception X, le nouveau est également complété exceptionnellement avec unCompletionException avec X comme cause

new CompletableFuture().copy()

Cette méthode peut être utile comme une forme de «copie défensive», pour empêcher les clients de terminer, tout en étant capable d'organiser des actions dépendantes sur une instance spécifique deCompletableFuture.

2.4. MéthodeminimalCompletionStage()

Signature:CompletionStage<T> minimalCompletionStage()

Cette méthode renvoie un nouveauCompletionStage qui se comporte exactement de la même manière que celle décrite par la méthode de copie, cependant, une telle nouvelle instance renvoieUnsupportedOperationException à chaque tentative de récupération ou de définition de la valeur résolue.

new CompletableFuture().minimalCompletionStage()

Un nouveauCompletableFuture avec toutes les méthodes disponibles peut être récupéré en utilisant la méthodetoCompletableFuture disponible sur l'APICompletionStage.

2.5. MéthodescompleteAsync()

La méthodecompleteAsync doit être utilisée pour compléter lesCompletableFuture de manière asynchrone en utilisant la valeur donnée par lesSupplier fournis.

Signatures:

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

La différence entre ces deux méthodes surchargées est l'existence du deuxième argument, où lesExecutor exécutant la tâche peuvent être spécifiés. Si aucun n'est fourni, l'exécuteur par défaut (retourné par la méthodedefaultExecutor) sera utilisé.

2.6. MéthodesorTimeout()

Signature:CompletableFuture<T> orTimeout(long timeout, TimeUnit unit)

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

Résout exceptionnellement lesCompletableFuture avecTimeoutException, à moins qu'il ne soit terminé avant le délai spécifié.

2.7. MéthodecompleteOnTimeout()

Signature:CompletableFuture<T> completeOnTimeout(T value, long timeout, TimeUnit unit)

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

Termine lesCompletableFuture normalement avec la valeur spécifiée à moins qu'il ne soit terminé avant le délai spécifié.

3. Ajouts d'API statiques

Certaines méthodes utilitaires ont également été ajoutées. Elles sont:

  1. Executor delayExecutor (long delay, unité TimeUnit, Executor executor)

  2. Executor delayExecutor (long delay, unité TimeUnit)

  3. CompletionStage completedStage (valeur U)

  4. CompletionStage échoué

  5. CompletableFuture failedFuture (Throwable ex)

3.1. MéthodesdelayedExecutor

Signatures:

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

Renvoie un nouveauExecutor qui soumet une tâche à l'exécuteur de base donné après le délai donné (ou pas de délai si non positif). Chaque délai commence lors de l’invocation de la méthode d’exécution de l’exécuteur renvoyé. Si aucun exécuteur n'est spécifié, l'exécuteur par défaut (ForkJoinPool.commonPool()) sera utilisé.

3.2. MéthodescompletedStage etfailedStage

Signatures:

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

Ces méthodes utilitaires renvoient des instancesCompletionStage déjà résolues, soit complétées normalement avec une valeur (completedStage), soit complétées exceptionnellement (failedStage) avec l'exception donnée.

3.3. MéthodefailedFuture

Signature:<U> CompletableFuture<U> failedFuture(Throwable ex)

La méthode failedFuture ajoute la possibilité de spécifier une instance deCompleatebleFuture déjà terminée exceptionnellement.

4. Exemples d'utilisation

Dans cette section, nous montrerons quelques exemples sur la façon d'utiliser certaines des nouvelles API.

4.1. Retard

Cet exemple montrera comment retarder l'achèvement d'unCompletableFuture avec une valeur spécifique d'une seconde. Cela peut être réalisé en utilisant la méthodecompleteAsync avec lesdelayedExecutor.

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



4.2. Complet avec Value on Timeout

Une autre façon d'obtenir un résultat différé consiste à utiliser la méthodecompleteOnTimeout. Cet exemple définit unCompletableFuture qui sera résolu avec une entrée donnée s'il reste non résolu après 1 seconde.

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



4.3. Temps libre

Une autre possibilité est l'expiration du délai qui résout le futur exceptionnellement avecTimeoutException. Par exemple, le délai d'expiration duCompletableFuture après 1 seconde étant donné qu'il n'est pas terminé avant cela.

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





5. Conclusion

En conclusion, Java 9 est livré avec plusieurs ajouts à l'APICompletableFuture, il a désormais un meilleur support pour le sous-classement, grâce au constructeur virtuelnewIncompleteFuture, il est possible de prendre le contrôle desCompletionStage instances renvoyées dans la plupart des APICompletionStage.

Comme indiqué précédemment, la prise en charge des retards et des délais d'attente est nettement meilleure. Les méthodes utilitaires ajoutées suivent un modèle raisonnable, donnant àCompletableFuture un moyen pratique de spécifier des instances résolues.

Les exemples utilisés dans cet article se trouvent dans nosGitHub repository.