Was ist der Unterschied zwischen Future
und Promise
?
Beide fungieren als Platzhalter für zukünftige Ergebnisse, aber wo liegt der Hauptunterschied?
java
concurrency
future
promise
user1170330
quelle
quelle
Promise
und es liegt an Ihnen, es zu behalten. Wenn jemand anderes Ihnen ein Versprechen macht, müssen Sie abwarten, ob er es imFuture
Antworten:
Nach dieser Diskussion ,
Promise
wird schließlich wurde genanntCompletableFuture
für die Aufnahme in Java 8 und seine javadoc erklärt:Ein Beispiel ist auch in der Liste angegeben:
Beachten Sie, dass sich die endgültige API geringfügig unterscheidet, jedoch eine ähnliche asynchrone Ausführung ermöglicht:
quelle
(Ich bin mit den Antworten bisher nicht ganz zufrieden, also hier ist mein Versuch ...)
Ich denke, dass Kevin Wrights Kommentar ( "Sie können ein Versprechen machen und es liegt an Ihnen, es zu halten. Wenn jemand anderes Ihnen ein Versprechen macht, müssen Sie abwarten, ob er es in Zukunft einhält" ) fasst es ziemlich gut zusammen, aber einige Erklärung kann nützlich sein.
Futures und Versprechen sind ziemlich ähnliche Konzepte. Der Unterschied besteht darin, dass eine Zukunft ein schreibgeschützter Container für ein Ergebnis ist, das noch nicht existiert, während ein Versprechen geschrieben werden kann (normalerweise nur einmal). Die Java 8 CompletableFuture und die Guava SettableFuture können als Versprechen angesehen werden, da ihr Wert festgelegt ("abgeschlossen") werden kann, sie aber auch die Future-Schnittstelle implementieren, sodass für den Client kein Unterschied besteht.
Das Ergebnis der Zukunft wird von "jemand anderem" festgelegt - durch das Ergebnis einer asynchronen Berechnung. Beachten Sie, dass FutureTask - eine klassische Zukunft - mit einem Callable oder Runnable initialisiert werden muss , es keinen Konstruktor ohne Argumente gibt und sowohl Future als auch FutureTask von außen schreibgeschützt sind (die festgelegten Methoden von FutureTask sind geschützt). Der Wert wird von innen auf das Ergebnis der Berechnung gesetzt.
Andererseits kann das Ergebnis eines Versprechens jederzeit von "Ihnen" (oder tatsächlich von irgendjemandem) festgelegt werden, da es über eine öffentliche Setter-Methode verfügt. Sowohl CompletableFuture als auch SettableFuture können ohne Aufgabe erstellt und ihr Wert kann jederzeit festgelegt werden. Sie senden ein Versprechen an den Kundencode und erfüllen es später nach Ihren Wünschen.
Beachten Sie, dass CompletableFuture kein "reines" Versprechen ist, sondern mit einer Aufgabe wie FutureTask initialisiert werden kann. Die nützlichste Funktion ist die unabhängige Verkettung von Verarbeitungsschritten.
Beachten Sie auch, dass ein Versprechen kein Subtyp der Zukunft sein muss und nicht dasselbe Objekt sein muss. In Scala wird ein Future-Objekt durch eine asynchrone Berechnung oder durch ein anderes Promise-Objekt erstellt. In C ++ ist die Situation ähnlich: Das Versprechen-Objekt wird vom Produzenten und das zukünftige Objekt vom Verbraucher verwendet. Der Vorteil dieser Trennung ist, dass der Kunde den Wert der Zukunft nicht festlegen kann.
Sowohl Spring als auch EJB 3.1 haben eine AsyncResult-Klasse, die den Scala / C ++ - Versprechungen ähnelt. AsyncResult implementiert Future, aber dies ist nicht die wirkliche Zukunft: Asynchrone Methoden in Spring / EJB geben durch Hintergrundmagie ein anderes schreibgeschütztes Future-Objekt zurück, und diese zweite "echte" Zukunft kann vom Client verwendet werden, um auf das Ergebnis zuzugreifen.
quelle
Mir ist bewusst, dass es bereits eine akzeptierte Antwort gibt, möchte aber trotzdem meine zwei Cent hinzufügen:
TLDR: Future und Promise sind die beiden Seiten einer asynchronen Operation: Consumer / Caller vs. Producer / Implementor .
Als Aufrufer einer asynchronen API-Methode erhalten Sie
Future
ein Handle für das Ergebnis der Berechnung. Sie können es beispielsweise aufrufen,get()
um zu warten, bis die Berechnung abgeschlossen ist, und das Ergebnis abzurufen.Stellen Sie sich nun vor, wie diese API-Methode tatsächlich implementiert ist: Der Implementierer muss
Future
sofort eine zurückgeben. Sie sind dafür verantwortlich, diese Zukunft abzuschließen, sobald die Berechnung abgeschlossen ist (was sie wissen werden, weil es die Versandlogik implementiert ;-)). Sie werden einPromise
/ verwendenCompletableFuture
, um genau das zu tun: Konstruieren und geben Sie dasCompletableFuture
sofort zurück und rufen Sie auf,complete(T result)
sobald die Berechnung abgeschlossen ist.quelle
Ich werde ein Beispiel geben, was Versprechen ist und wie sein Wert jederzeit eingestellt werden kann, im Gegensatz zu Future, wobei dieser Wert nur lesbar ist.
Angenommen, Sie haben eine Mutter und bitten sie um Geld.
Die Ausgabe davon ist:
Mamas Versprechen wurde erstellt, wartete aber auf ein "Abschluss" -Ereignis.
Sie haben ein solches Ereignis ins Leben gerufen, ihr Versprechen angenommen und Ihre Pläne angekündigt, Ihrer Mutter zu danken:
In diesem Moment fing Mama an, ihre Handtasche zu öffnen ... aber sehr langsam ...
und Vater mischte sich viel schneller ein und erfüllte das Versprechen anstelle deiner Mutter:
Haben Sie einen Testamentsvollstrecker bemerkt, den ich explizit geschrieben habe?
Interessanterweise wird ihr Versprechen nur dann erfüllt, wenn Sie stattdessen einen impliziten Standard-Executor (commonPool) verwenden und der Vater nicht zu Hause ist, sondern nur die Mutter mit ihrem "langsamen Geldbeutel", wenn das Programm länger lebt, als die Mutter Geld von der benötigt Geldbörse.
Der Standard-Executor verhält sich wie ein "Daemon" und wartet nicht darauf, dass alle Versprechen erfüllt werden. Ich habe keine gute Beschreibung dieser Tatsache gefunden ...
quelle
Ich bin mir nicht sicher, ob dies eine Antwort sein kann, aber wie ich sehe, was andere für jemanden gesagt haben, sieht es möglicherweise so aus, als ob Sie für beide Konzepte zwei separate Abstraktionen benötigen, sodass eine von ihnen (
Future
) nur eine schreibgeschützte Ansicht der anderen ist (Promise
) ... aber eigentlich wird das nicht benötigt.Schauen Sie sich zum Beispiel an, wie Versprechen in Javascript definiert sind:
https://promisesaplus.com/
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Der Fokus liegt auf der Zusammensetzbarkeit mit der
then
Methode wie:Dadurch sieht die asynchrone Berechnung synchron aus:
Das ist ziemlich cool. (Nicht so cool wie async-await, aber async-await entfernt nur die Boilerplate .... then (function (result) {.... from it).
Und tatsächlich ist ihre Abstraktion als Versprechenskonstruktor ziemlich gut
Mit dieser Option können Sie zwei Rückrufe bereitstellen, mit denen Sie den Vorgang entweder
Promise
erfolgreich oder mit einem Fehler abschließen können . Damit nur der Code, der dasPromise
erstellt, es vervollständigen kann und der Code, der ein bereits erstelltesPromise
Objekt empfängt, die schreibgeschützte Ansicht hat.Mit der Vererbung kann das Obige erreicht werden, wenn Auflösung und Zurückweisung geschützte Methoden sind.
quelle
CompletableFuture
Möglicherweise hat es eine gewisse Ähnlichkeit mit a,Promise
aber es ist immer noch keinePromise
, da die Art und Weise, wie es konsumiert werden soll, unterschiedlich ist:Promise
Das Ergebnis von a wird durch Aufrufen konsumiertthen(function)
, und die Funktion wird unmittelbar nach dem Aufruf des Produzenten im Kontext des Produzenten ausgeführtresolve
.Future
Das Ergebnis von A wird durch einen Aufruf verbraucht,get
wodurch der Consumer-Thread wartet, bis der Producer-Thread den Wert generiert hat, und ihn dann im Consumer verarbeitet.Future
ist von Natur aus multithreaded, aber ...Promise
mit nur einem Thread zu verwenden (und tatsächlich ist dies die genaue Umgebung, für die sie ursprünglich entwickelt wurden: Javascript-Anwendungen haben im Allgemeinen nur einen einzigen Thread, sodass Sie sie dort nicht implementierenFuture
können).Promise
ist daher viel leichter und effizienter alsFuture
,Future
kann aber in Situationen hilfreich sein, die komplexer sind und die Zusammenarbeit zwischen Threads erfordern, die mitPromise
s nicht einfach angeordnet werden können . Zusammenfassend:Promise
ist ein Push-Modell, währendFuture
es ein Pull-Modell ist (vgl. Iterable vs Observable)XMLHttpRequest
. B. ein ). Ich glaube dem Effizienzanspruch nicht, haben Sie zufällig Zahlen? +++ Das heißt, eine sehr schöne Erklärung.get
eines ungelöstenFuture
Problems zwangsläufig zwei Thread-Kontextwechsel erfordert, für die vor mindestens einigen Jahren wahrscheinlich etwa 50 US erforderlich waren .Bei Client-Code dient Promise zum Beobachten oder Anhängen eines Rückrufs, wenn ein Ergebnis verfügbar ist, während Future auf das Ergebnis warten und dann fortfahren soll. Theoretisch alles, was mit Futures zu tun ist, was mit Versprechungen getan werden kann, aber aufgrund des Stilunterschieds erleichtert die resultierende API für Versprechungen in verschiedenen Sprachen die Verkettung.
quelle
Keine festgelegte Methode in der Future-Schnittstelle, nur get-Methode, daher schreibgeschützt. Über CompletableFuture kann dieser Artikel hilfreich sein. vervollständigbare Zukunft
quelle