Sowohl Futures als auch Versprechen blockieren, bis sie ihre Werte berechnet haben. Was ist also der Unterschied zwischen ihnen?
Sowohl Futures als auch Versprechen blockieren, bis sie ihre Werte berechnet haben. Was ist also der Unterschied zwischen ihnen?
Antworten:
In Clojure-Begriffen antworten, hier einige Beispiele aus Sean Devlins Screencast :
(def a-promise (promise))
(deliver a-promise :fred)
(def f (future (some-sexp)))
(deref f)
Beachten Sie, dass Sie im Versprechen explizit einen Wert liefern, den Sie in einer späteren Berechnung ( :fred
in diesem Fall) auswählen . Die Zukunft hingegen wird an dem Ort konsumiert, an dem sie geschaffen wurde. Das some-expr
wird vermutlich hinter den Kulissen gestartet und (eventuell) im Tandem berechnet. Wenn es jedoch zum Zeitpunkt des Zugriffs nicht bewertet wird, werden die Thread-Blöcke bis zur Verfügbarkeit angezeigt.
bearbeitet, um hinzuzufügen
Beachten Sie Folgendes, um die Unterscheidung zwischen einem Versprechen und einer Zukunft zu erleichtern:
promise
. Dieses Versprechungsobjekt kann jetzt an einen beliebigen Thread übergeben werden.deliver
die Ergebnisse für dieses Versprechenobjekt anzeigen.deref
Ihr Versprechen zu erfüllen, bevor Sie mit Ihrer Berechnung fertig sind, wird blockiert, bis Sie fertig sind. Sobald Sie fertig sind und deliver
das Versprechen eingelöst haben, wird das Versprechen nicht mehr blockiert.deref
die Zukunft. Wenn die Berechnung bereits abgeschlossen ist, erhalten Sie die Ergebnisse. Wenn es noch nicht abgeschlossen ist, blockieren Sie, bis es abgeschlossen ist. (Wenn es vermutlich noch nicht gestartet wurde, deref
bedeutet dies, dass es ausgeführt wird, aber auch dies ist nicht garantiert.)Während Sie den Ausdruck in Zukunft so kompliziert machen könnten wie den Code, der auf die Erstellung eines Versprechens folgt, ist es zweifelhaft, dass dies wünschenswert ist. Dies bedeutet, dass Futures eher für schnelle, hintergrundfähige Berechnungen geeignet sind, während Versprechen eher für große, komplizierte Ausführungspfade geeignet sind. Außerdem scheinen Versprechen in Bezug auf die verfügbaren Berechnungen etwas flexibler und auf den Versprechensschöpfer ausgerichtet zu sein, der die Arbeit erledigt, und auf einen anderen Faden, der die Ernte erntet. Futures sind eher darauf ausgerichtet, einen Thread automatisch zu starten (ohne den hässlichen und fehleranfälligen Overhead) und mit anderen Dingen fortzufahren, bis Sie - der ursprüngliche Thread - die Ergebnisse benötigen.
future
Veranschaulichung , der Hauptteil eines Anrufs kann N sexprs enthalten.
Sowohl Future als auch Promise sind Mechanismen zur Kommunikation des Ergebnisses asynchroner Berechnungen vom Produzenten an den Verbraucher.
Im Falle von Future wird die Berechnung zum Zeitpunkt der Future-Erstellung definiert und die asynchrone Ausführung beginnt "ASAP". Es "weiß" auch, wie eine asynchrone Berechnung erzeugt wird.
Im Falle des Versprechens werden die Berechnung , die Startzeit und der [mögliche] asynchrone Aufruf vom Übermittlungsmechanismus entkoppelt. Wenn das Berechnungsergebnis verfügbar ist, muss der Produzent deliver
explizit aufrufen. Dies bedeutet auch, dass der Produzent steuert, wann das Ergebnis verfügbar wird.
Für Versprechen macht Clojure einen Entwurfsfehler, indem er dasselbe Objekt (Ergebnis des promise
Aufrufs) verwendet, um das Ergebnis der Berechnung zu erzeugen ( deliver
) und zu verbrauchen ( deref
) . Dies sind zwei sehr unterschiedliche Fähigkeiten, die als solche behandelt werden sollten.
promise
es bequem wäre, die Sicherheit an einen so einfachen Referenztyp zu koppeln (siehe Impl) . "Böse" Verbraucher sind selten; Nichts hindert Sie daran, Ihre eigene Abstraktion auf Versprechungen aufzubauen.
(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))))
Es gibt bereits hervorragende Antworten, daher wird nur die Zusammenfassung "Verwendung" hinzugefügt:
Beide
Wenn Sie ein Versprechen oder eine Zukunft erstellen, wird sofort eine Referenz zurückgegeben. Diese Referenz blockiert @ / deref, bis das Ergebnis der Berechnung von einem anderen Thread bereitgestellt wird.
Zukunft
Beim Erstellen einer Zukunft stellen Sie einen synchronen Job bereit, der ausgeführt werden muss. Es wird in einem Thread aus dem dedizierten unbegrenzten Pool ausgeführt.
Versprechen
Sie geben keine Argumente an, wenn Sie ein Versprechen erstellen. Die Referenz sollte an einen anderen 'Benutzer'-Thread übergeben werden, der deliver
das Ergebnis liefert.
In Clojure, promise
, future
, und delay
sind Versprechen ähnliche Objekte. Sie alle stellen eine Berechnung dar, auf die Clients mit deref
(oder @
) warten können . Clients verwenden das Ergebnis erneut, sodass die Berechnung nicht mehrmals ausgeführt wird.
Sie unterscheiden sich in der Art und Weise, wie die Berechnung durchgeführt wird:
future
startet die Berechnung in einem anderen Worker-Thread. deref
wird blockiert, bis das Ergebnis fertig ist.
delay
führt die Berechnung träge durch, wenn der erste Client verwendet deref
, oder force
.
promise
bietet die größte Flexibilität, da das Ergebnis durch Verwendung auf jede benutzerdefinierte Weise geliefert wird deliver
. Sie verwenden es, wenn keines future
oder delay
Ihr Anwendungsfall übereinstimmt.
Erstens ist a Promise
a Future
. Ich denke, Sie möchten den Unterschied zwischen a Promise
und a kennen FutureTask
.
A Future
stellt einen Wert dar, der derzeit nicht bekannt ist, aber in Zukunft bekannt sein wird.
A FutureTask
stellt das Ergebnis einer Berechnung dar, die in Zukunft stattfinden wird (möglicherweise in einem Thread-Pool). Wenn Sie versuchen, auf das Ergebnis zuzugreifen, wird die Berechnung blockiert, wenn sie noch nicht erfolgt ist. Andernfalls wird das Ergebnis sofort zurückgegeben. Es ist keine andere Partei an der Berechnung des Ergebnisses beteiligt, da die Berechnung von Ihnen im Voraus festgelegt wurde.
A Promise
stellt ein Ergebnis dar, das der Versprechende dem Versprechenden in Zukunft liefern wird. In diesem Fall sind Sie der Versprechende und der Versprechende ist derjenige, der Ihnen das Promise
Objekt gegeben hat. Ähnlich wie bei FutureTask
, wenn Sie versuchen, auf das Ergebnis zuzugreifen, bevor das Promise
erfüllt wurde, wird es blockiert, bis der Promiser das erfüllt Promise
. Sobald das Promise
erfüllt ist, erhalten Sie immer und sofort den gleichen Wert. Im Gegensatz zu a FutureTask
ist hier eine andere Partei beteiligt, die die Promise
. Dass eine andere Partei für die Berechnung und Erfüllung der Promise
.
In diesem Sinne ist a FutureTask
ein, das Promise
du dir selbst gemacht hast.