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 ( :freddans ce cas). L'avenir, par contre, est consommé au même endroit où il a été créé. Le some-exprest 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.deliverles résultats de cet objet promis.derefvotre 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é deliverla promesse, la promesse ne se bloquera plus.derefl'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é, derefcela 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.
futureappel 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 deliverexplicitement, 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' promiseappel) 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.
promiseserait 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 deliverle résultat.
En Clojure, promise, futureet delaysont 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é:
futuredémarrera le calcul dans un thread de travail différent. derefbloquera jusqu'à ce que le résultat soit prêt.
delayeffectuera le calcul paresseusement, lorsque le premier client utilise deref, ou force.
promiseoffre la plus grande flexibilité, car son résultat est fourni de manière personnalisée en utilisant deliver. Vous l'utilisez lorsque ni futureni ne delaycorrespond à votre cas d'utilisation.
Premièrement, a Promiseest un Future. Je pense que vous voulez connaître la différence entre a Promiseet a FutureTask.
A Futurereprésente une valeur qui n'est pas connue actuellement mais qui sera connue dans le futur.
A FutureTaskrepré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 Promiserepré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' Promiseobjet. Semblable à la FutureTask, si vous essayez d'accéder au résultat avant que le Promisen'ait été exécuté, il est bloqué jusqu'à ce que le prometteur remplisse le Promise. Une fois que le Promiseest 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 FutureTaskest un Promisevous fait pour vous-même.