2016-10-21 3 views
3

J'ai un malentendu à propos de the contract de thenCompose(Function<? super T,? extends CompletionStage<U>> fn). Voici ce qui est dit là:CompletableFuture, thenCompose méthode

Renvoie une nouvelle CompletionStage que, lorsque cette étape complète normalement, est exécuté avec ce stade que l'argument de la fonction fournie.

Il semble que la fonction accepte le résultat de cette CompletionStage, pas le CompletionStage lui-même. Alors qu'est-ce qu'ils veulent dire par là?

Et qu'en est-il de la tâche représentée par le CompletableFuture retourné?

Runnable r; 
ExecutorService es; 
Function<Void, CompletableFuture<Void>>f; 
//... 
CompletableFuture.runAsync(r, es) 
.thenCompose(f); 

Est-ce que cela signifie, une tâche, représenter par CompletableFuture retourné par thenCompose seront exécutés dans le même ThreadPool que le Runnable r?

+2

Le document est mal rédigé - il devrait indiquer "* avec le résultat de cette étape comme argument de la fonction fournie *". 'f' sera exécuté en utilisant' es'. – assylias

+2

Le chemin, le 'CompletableFuture' sera terminé, a déjà été défini par la fonction' f' * avant * il le retourne. – Holger

+0

@Holger Que voulez-vous dire? D'abord, nous appelons 'runAsync' qui soumet' Runnable' à 'ThreadPool'. Il peut arriver que le futur soit complété ** avant que ** thenCompose ne soit appelé (l'évaluation des arguments de 'thenCompose' peut prendre un certain temps). –

Répondre

1

Cela semble être une erreur dans JavaDoc. D'autres méthodes telles que thenApply utilisent la formulation suivante:

Renvoie une nouvelle CompletionStage que, lorsque cette étape complète normalement, est exécuté avec ce résultat de stade que l'argument de la fonction fournie . [...]

(l'accent est ma propre)

En outre, en Java 9, le formulation is now:

Renvoie une nouvelle CompletionStage qui est complétée par la même valeur que le CompletionStage retourné par la fonction donnée.

Lorsque cette étape se termine normalement, la fonction donnée est invoquée avec résultat de cette étape comme argument, retournant une autre CompletionStage. Lorsque cette étape se termine normalement, le CompletionStage retourné par cette méthode est complété avec la même valeur . [...]

En ce qui concerne le thread/pool de threads exécutera la fonction, cela dépendra réellement de l'implémentation.

Pour CompletableFuture, cela est indiqué en haut de la documentation:

Actions fourni pour les achèvements dépendantes de non async méthodes peuvent être effectuées par le thread qui complète le CompletableFuture en cours, ou par tout autre appelant d'une méthode d'achèvement.

Dans la pratique, il semble y avoir 2 cas possibles:

  1. Si cette étape est déjà terminée, la fonction est appliquée immédiatement sur le thread appelant thenCompose();
  2. Si cette étape n'est pas encore terminée, la fonction sera appliquée sur le thread qui termine cette étape (corrigez-moi si c'est faux).

Notez qu'il n'y a pas de "tâche" dans un CompletableFuture. La seule "tâche" renvoyée par le CompletableFuture renvoyé lie le résultat de celui renvoyé par la fonction passée avec lui-même. Vous êtes en charge de l'exécution de la tâche qui va compléter le CompletableFuture votre fonction retourne.

+1

En fait, même le "binding" n'est pas une tâche du futur retourné; c'est une tâche liée au futur renvoyé par la fonction. Ou, en d'autres termes, 'CompletableFuture's sont * jamais * associés aux tâches qui finiront par les compléter, ils ne les connaissent même pas. Ils seulement maintenant les étapes dépendantes qu'ils doivent notifier. – Holger