Les futurs et les promesses se bloquent jusqu'à ce qu'ils aient calculé leurs valeurs, alors quelle est la différence entre eux?
Les futurs et les promesses se bloquent jusqu'à ce qu'ils aient calculé leurs valeurs, alors quelle est la différence entre eux?
Réponses:
Répondant en termes de Clojure, voici quelques exemples tirés du screencast de Sean Devlin :
(def a-promise (promise))
(deliver a-promise :fred)
(def f (future (some-sexp)))
(deref f)
Notez que dans la promesse, vous fournissez explicitement une valeur que vous sélectionnez dans un calcul ultérieur ( :fred
dans ce cas). L'avenir, par contre, est consommé au même endroit où il a été créé. Le some-expr
est probablement lancé dans les coulisses et calculé en tandem (éventuellement), mais s'il reste non évalué au moment où il est accédé, le thread se bloque jusqu'à ce qu'il soit disponible.
modifié pour ajouter
Pour mieux faire la distinction entre une promesse et un avenir, notez ce qui suit:
promise
. Cet objet de promesse peut maintenant être passé à n'importe quel thread.deliver
les résultats de cet objet promis.deref
votre promesse avant que vous ayez terminé votre calcul sera bloqué jusqu'à ce que vous ayez terminé. Une fois que vous avez terminé et que vous avez exécuté deliver
la promesse, la promesse ne se bloquera plus.deref
l'avenir. Si le calcul est déjà terminé, vous en obtenez les résultats. Si ce n'est pas déjà fait, vous bloquez jusqu'à ce que ce soit le cas. (Probablement s'il n'a pas encore démarré, deref
cela signifie qu'il commence à s'exécuter, mais cela n'est pas non plus garanti.)Bien que vous puissiez rendre l'expression à l'avenir aussi compliquée que le code qui suit la création d'une promesse, il est peu probable que ce soit souhaitable. Cela signifie que les contrats à terme sont vraiment plus adaptés aux calculs rapides et en arrière-plan, tandis que les promesses sont vraiment plus adaptées aux chemins d'exécution longs et complexes. Aussi, les promesses semblent, en termes de calculs disponibles, un peu plus flexibles et orientées vers le créateur de promesses faisant le travail et un autre fil récoltant la récolte. Les contrats à terme sont davantage orientés vers le démarrage automatique d'un thread (sans la surcharge laide et sujette aux erreurs) et vers d'autres choses jusqu'à ce que vous - le thread d'origine - ayez besoin des résultats.
future
appel peut inclure N sexprs.
Future et Promise sont des mécanismes pour communiquer le résultat du calcul asynchrone du producteur au (x) consommateur (s).
Dans le cas de Future, le calcul est défini au moment de la création Future et l'exécution asynchrone commence "ASAP". Il "sait" également comment générer un calcul asynchrone.
Dans le cas de Promise, le calcul , son heure de début et son [possible] appel asynchrone sont découplés du mécanisme de livraison. Lorsque le résultat du calcul est disponible, le producteur doit appeler deliver
explicitement, ce qui signifie également que le producteur contrôle le moment où le résultat devient disponible.
Pour les promesses, Clojure commet une erreur de conception en utilisant le même objet (résultat de l' promise
appel) pour produire ( deliver
) et consommer ( deref
) le résultat du calcul . Ce sont deux capacités très distinctes et doivent être traitées comme telles.
promise
serait pratique. Les consommateurs «mauvais» sont rares; rien ne vous empêche de construire votre propre abstraction en plus de promesses.
(defn undeliverable-promise [] (let [p (promise)] (reify clojure.lang.IDeref (deref [_] (deref p)) clojure.lang.IBlockingDeref (deref [_ ms val] (deref p ms val)) clojure.lang.IPending (isRealized [_] (.isRealized p)) clojure.lang.IFn (invoke [_ _] nil))))
Il y a déjà d'excellentes réponses donc n'ajoutez que le résumé "comment utiliser":
Tous les deux
La création d'une promesse ou d'un futur renvoie une référence immédiatement. Cette référence se bloque sur @ / deref jusqu'à ce que le résultat du calcul soit fourni par un autre thread.
Futur
Lors de la création du futur, vous fournissez un travail synchrone à faire. Il est exécuté dans un thread du pool illimité dédié.
Promettre
Vous ne donnez aucun argument lors de la création de la promesse. La référence doit être passée à un autre thread «utilisateur» qui donnera deliver
le résultat.
En Clojure, promise
, future
et delay
sont la promesse comme des objets. Ils représentent tous un calcul que les clients peuvent attendre en utilisant deref
(ou @
). Les clients réutilisent le résultat, de sorte que le calcul ne soit pas exécuté plusieurs fois.
Ils diffèrent dans la manière dont le calcul est effectué:
future
démarrera le calcul dans un thread de travail différent. deref
bloquera jusqu'à ce que le résultat soit prêt.
delay
effectuera le calcul paresseusement, lorsque le premier client utilise deref
, ou force
.
promise
offre la plus grande flexibilité, car son résultat est fourni de manière personnalisée en utilisant deliver
. Vous l'utilisez lorsque ni future
ni ne delay
correspond à votre cas d'utilisation.
Premièrement, a Promise
est un Future
. Je pense que vous voulez connaître la différence entre a Promise
et a FutureTask
.
A Future
représente une valeur qui n'est pas connue actuellement mais qui sera connue dans le futur.
A FutureTask
représente le résultat d'un calcul qui se produira à l'avenir (peut-être dans un pool de threads). Lorsque vous essayez d'accéder au résultat, si le calcul n'a pas encore eu lieu, il se bloque. Sinon, le résultat est renvoyé immédiatement. Il n'y a aucune autre partie impliquée dans le calcul du résultat car le calcul est spécifié par vous à l'avance.
A Promise
représente un résultat qui sera livré par le promettant au promettant à l'avenir. Dans ce cas, vous êtes le promis et le prometteur est celui qui vous a donné l' Promise
objet. Semblable à la FutureTask
, si vous essayez d'accéder au résultat avant que le Promise
n'ait été exécuté, il est bloqué jusqu'à ce que le prometteur remplisse le Promise
. Une fois que le Promise
est rempli, vous obtenez toujours et immédiatement la même valeur. Contrairement à a FutureTask
, il y a une autre partie impliquée ici, une qui a fait le Promise
. Qu'une autre partie est responsable du calcul et de l'exécution du Promise
.
En ce sens, un FutureTask
est un Promise
vous fait pour vous-même.