Quelle est la différence entre Future
et Promise
?
Ils agissent tous deux comme un espace réservé pour les résultats futurs, mais où est la principale différence?
java
concurrency
future
promise
user1170330
la source
la source
Promise
et c'est à vous de le garder. Quand quelqu'un d'autre vous fait une promesse, vous devez attendre de voir s'il l'honore dans leFuture
Réponses:
Selon cette discussion ,
Promise
a finalement été appeléCompletableFuture
à être inclus dans Java 8, et son javadoc explique:Un exemple est également donné sur la liste:
Notez que l'API finale est légèrement différente mais permet une exécution asynchrone similaire:
la source
(Je ne suis pas complètement satisfait des réponses jusqu'à présent, alors voici ma tentative ...)
Je pense que le commentaire de Kevin Wright ( "Vous pouvez faire une promesse et c'est à vous de la tenir. Quand quelqu'un d'autre vous fait une promesse, vous devez attendre de voir s'il l'honorera dans le futur" ) le résume assez bien, mais certains l'explication peut être utile.
Futures et promesses sont des concepts assez similaires, la différence est qu'un futur est un conteneur en lecture seule pour un résultat qui n'existe pas encore, alors qu'une promesse peut être écrite (normalement une seule fois). Le Java 8 CompletableFuture et le Guava SettableFuture peuvent être considérés comme des promesses, car leur valeur peut être définie ("terminée"), mais ils implémentent également l'interface Future, il n'y a donc pas de différence pour le client.
Le résultat du futur sera fixé par "quelqu'un d'autre" - par le résultat d'un calcul asynchrone. Notez comment FutureTask - un futur classique - doit être initialisé avec un Callable ou Runnable, il n'y a pas de constructeur sans argument, et Future et FutureTask sont en lecture seule de l'extérieur (les méthodes définies de FutureTask sont protégées). La valeur sera définie sur le résultat du calcul de l'intérieur.
D'un autre côté, le résultat d'une promesse peut être défini par "vous" (ou en fait par n'importe qui) à tout moment car il a une méthode de définition publique. CompletableFuture et SettableFuture peuvent être créés sans aucune tâche et leur valeur peut être définie à tout moment. Vous envoyez une promesse au code client et la remplissez plus tard comme vous le souhaitez.
Notez que CompletableFuture n'est pas une promesse "pure", il peut être initialisé avec une tâche tout comme FutureTask, et sa fonctionnalité la plus utile est le chaînage indépendant des étapes de traitement.
Notez également qu'une promesse n'a pas à être un sous-type de futur et qu'elle ne doit pas être le même objet. Dans Scala, un objet Future est créé par un calcul asynchrone ou par un autre objet Promise. En C ++ la situation est similaire: l'objet promesse est utilisé par le producteur et l'objet futur par le consommateur. L'avantage de cette séparation est que le client ne peut pas fixer la valeur de l'avenir.
Les deux printemps et EJB 3.1 ont une classe AsyncResult, qui est semblable aux promesses de la / Scala C. AsyncResult implémente Future mais ce n'est pas le vrai futur: les méthodes asynchrones dans Spring / EJB renvoient un objet Future différent et en lecture seule via une magie d'arrière-plan, et ce deuxième futur "réel" peut être utilisé par le client pour accéder au résultat.
la source
Je suis conscient qu'il existe déjà une réponse acceptée, mais je voudrais néanmoins ajouter mes deux cents:
TLDR: Future et Promise sont les deux faces d'une opération asynchrone: consommateur / appelant vs producteur / réalisateur .
En tant qu'appelant d'une méthode d'API asynchrone, vous obtiendrez un en
Future
tant que descripteur du résultat du calcul. Vous pouvez par exemple l'appelerget()
pour attendre la fin du calcul et récupérer le résultat.Pensez maintenant à la façon dont cette méthode API est réellement implémentée: l' implémenteur doit retourner
Future
immédiatement un . Ils sont chargés de compléter cet avenir dès que le calcul est terminé (ce qu'ils sauront car il implémente la logique de répartition ;-)). Ils utiliseront aPromise
/CompletableFuture
pour faire exactement cela: Construire et retourner leCompletableFuture
immédiatement, et appelercomplete(T result)
une fois le calcul terminé.la source
Je vais donner un exemple de ce qu'est Promise et comment sa valeur pourrait être définie à tout moment, contrairement à Future, qui est uniquement lisible.
Supposons que vous ayez une maman et que vous lui demandiez de l'argent.
La sortie de cela est:
La promesse de maman a été créée, mais a attendu un événement "d'achèvement".
Vous avez créé un tel événement, en acceptant sa promesse et en annonçant vos plans pour remercier votre maman:
À ce moment, maman a commencé à ouvrir son sac à main ... mais très lentement ...
et le père est intervenu beaucoup plus rapidement et a rempli la promesse au lieu de votre maman:
Avez-vous remarqué un exécuteur que j'ai écrit explicitement?
Fait intéressant, si vous utilisez un exécuteur implicite implicite à la place (commonPool) et que le père n'est pas à la maison, mais seulement maman avec son "sac à main lent", alors sa promesse ne se terminera que si le programme vit plus longtemps que maman a besoin d'obtenir de l'argent du bourse.
L'exécuteur par défaut agit un peu comme un "démon" et n'attend pas que toutes les promesses soient tenues. Je n'ai pas trouvé une bonne description de ce fait ...
la source
Je ne sais pas si cela peut être une réponse, mais comme je vois ce que les autres ont dit pour quelqu'un, il peut sembler que vous avez besoin de deux abstractions distinctes pour ces deux concepts afin que l'un d'eux (
Future
) soit juste une vue en lecture seule de l'autre (Promise
) ... mais en fait ce n'est pas nécessaire.Par exemple, regardez comment les promesses sont définies en javascript:
https://promisesaplus.com/
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
L'accent est mis sur la composabilité en utilisant la
then
méthode comme:ce qui rend le calcul asynchrone comme synchrone:
ce qui est plutôt cool. (Pas aussi cool que async-wait mais async-wait supprime simplement le passe-partout .... puis (fonction (résultat) {.... de celui-ci).
Et en fait, leur abstraction est assez bonne en tant que constructeur de promesses
vous permet de fournir deux rappels qui peuvent être utilisés pour terminer
Promise
avec succès ou avec une erreur. Ainsi, seul le code qui construit lePromise
peut le compléter et le code qui reçoit unPromise
objet déjà construit a la vue en lecture seule.Avec l'héritage, ce qui précède peut être atteint si la résolution et le rejet sont des méthodes protégées.
la source
CompletableFuture
peut avoir une certaine similitude avec aPromise
mais ce n'est toujours pas le casPromise
, car la façon dont il est destiné à être consommé est différente:Promise
le résultat de a est consommé en appelantthen(function)
, et la fonction est exécutée dans le contexte du producteur immédiatement après l'appel du producteurresolve
. LeFuture
résultat de A est consommé en appelant,get
ce qui oblige le thread consommateur à attendre que le thread producteur ait généré la valeur, puis la traite dans le consommateur.Future
est intrinsèquement multithread, mais ...Promise
avec un seul thread (et en fait c'est l'environnement précis pour lequel ils ont été initialement conçus: les applications javascript n'ont généralement qu'un seul thread, vous ne pouvez donc pas les implémenterFuture
).Promise
est donc beaucoup plus léger et efficace queFuture
, maisFuture
peut être utile dans des situations plus complexes et nécessitant une coopération entre des threads qui ne peuvent pas être facilement arrangés en utilisantPromise
s. Pour résumer:Promise
est un modèle push, tandis queFuture
est un modèle pull (cf Iterable vs Observable)XMLHttpRequest
). Je ne crois pas à la revendication d'efficacité, avez-vous des chiffres? +++ Cela dit, une très belle explication.get
à une solution non résolueFuture
impliquera nécessairement 2 changements de contexte de threads, ce qui, au moins quelques années auparavant, nécessiterait probablement une cinquantaine de nous .Pour le code client, Promise permet d'observer ou de joindre un rappel lorsqu'un résultat est disponible, alors que Future attend le résultat et continue. Théoriquement tout ce qui est possible de faire avec les futurs ce qui peut être fait avec les promesses, mais en raison de la différence de style, l'API résultante pour les promesses dans différentes langues facilite le chaînage.
la source
Aucune méthode définie dans l'interface Future, uniquement la méthode get, elle est donc en lecture seule. À propos de CompletableFuture, cet article peut être utile. completablefuture
la source