Was ist der Unterschied zwischen einem Future und einem Versprechen?
Was ist der Unterschied zwischen Future
und Promise
?
Sie beide wirken wie Platzhalter für künftige Ergebnisse, aber wo ist der Unterschied?
- Sie können eine
Promise
und es ist bis zu Ihnen, es zu halten. Wenn jemand anderes Sie macht ein Versprechen müssen Sie warten, um zu sehen, wenn Sie Ehre, die es in derFuture
- wikipedia Futures und promises
- Eine der am wenigsten hilfreichen Wikipedia-Artikel die ich je gelesen habe
- dist-prog-book.com/chapter/2/futures.html
Du musst angemeldet sein, um einen Kommentar abzugeben.
Laut diese Diskussion,
Promise
wurde endlich genanntCompletableFuture
für die Aufnahme in Java 8, und seine javadoc erklärt:Beispiel ist auch auf der Liste:
Beachten Sie, dass die endgültige API ist leicht unterschiedlich, aber erlaubt, ähnlich der asynchronen Ausführung:
(Ich bin nicht ganz zufrieden mit den Antworten so weit, so hier ist mein Versuch...)
Ich denke, dass Kevin Wright ' s Kommentar ("Sie können machen ein Versprechen und es ist an Ihnen, es zu halten. Wenn jemand anderes Sie macht ein Versprechen müssen Sie warten, um zu sehen, wenn Sie Ehre, die es in der Zukunft") fasst es schon ziemlich gut, aber eine Erklärung kann hilfreich sein.
Futures und promises sind ziemlich ähnliche Konzepte, der Unterschied ist, dass ein future ist ein nur-lese-container für ein Ergebnis, das noch nicht existiert, während ein Versprechen geschrieben werden können (in der Regel nur einmal). Die Java-8 CompletableFuture und die Guave SettableFuture gedacht werden kann, wie versprochen, weil Ihr Wert gesetzt werden können ("abgeschlossen"), aber auch die Umsetzung der Künftigen Schnittstelle, daher gibt es keinen Unterschied für den Klienten.
Das Ergebnis der Zukunft festgelegt werden "jemand anderes" - das Ergebnis einer asynchronen Berechnung. Beachten Sie, wie FutureTask - ein Klassiker der Zukunft - muss initialisiert werden mit einem Callable oder Runnable, es gibt keine no-argument-Konstruktor, und beide Zukunft und FutureTask gelesen werden-nur von außen (die set-Methoden von FutureTask geschützt sind). Der Wert wird festgelegt, um das Ergebnis der Berechnung von innen.
Auf der anderen Seite, ist das Ergebnis eines Versprechens festgelegt werden kann, "Sie" (oder in der Tat, die von jedermann jederzeit, weil es eine öffentliche setter-Methode. Beide CompletableFuture und SettableFuture erstellt werden können, ohne Aufgabe, und Ihr Wert kann festgelegt werden, zu jeder Zeit. Senden Sie ein Versprechen an den client-code, und erfüllen Sie es später, wie Sie wollen.
Beachten Sie, dass CompletableFuture ist nicht eine "Reine" Versprechen, es kann initialisiert werden, mit einer Aufgabe genau wie FutureTask, und die nützliche Funktion, ist das nicht verbundene Verkettung von Bearbeitungsschritten.
Beachten Sie auch, dass ein Versprechen nicht ein Untertyp von Zukunft, und es muss sich nicht um das gleiche Objekt. In Scala ein Future-Objekt wird erstellt, indem eine asynchrone Berechnung oder durch eine verschiedenen Promise-Objekt. In C++ ist die situation ähnlich: der promise-Objekt ist, verwendet der Produzent und das künftige Objekt durch den Verbraucher. Der Vorteil dieser Trennung ist, dass der client kann nicht den Wert der Zukunft.
Beide Frühling und EJB 3.1 haben ein AsyncResult-Klasse, die ähnlich wie die Scala/C++ verspricht. AsyncResult tut implementieren Zukunft, aber dies ist nicht die Reale Zukunft: asynchrone Methoden in Spring/EJB-Rückkehr einer anderen, nur-lese-Future-Objekt über einige hintergrund-Magie, und diese zweite "Reale" Zukunft, die der client verwendet, um den Zugriff auf das Ergebnis.
Ich bin mir bewusst, dass es bereits eine akzeptierte Antwort, möchte aber noch hinzufügen meine zwei Cent dennoch:
TLDR: Zukunft und Versprechen sind zwei Seiten einer asynchronen operation: Verbraucher/Anrufer - vs. Hersteller/implementor.
Als Anrufer eine asynchrone API-Methode, erhalten Sie ein
Future
als Griff, um die Berechnung Ergebnis. Sie können z.B. call -get()
auf es zu warten, bis die Berechnung zu vervollständigen, und um das Ergebnis abzurufen.Nun überlegen Sie, wie diese API-Methode tatsächlich umgesetzt werden: Die Implementierung muss wieder ein
Future
sofort. Sie sind zuständig für den Abschluss, die Zukunft, sobald die Berechnung fertig ist (was Sie wissen, denn es ist die Implementierung der dispatch-Logik ;-)). Werden Sie mitPromise
/CompletableFuture
genau das zu tun: die Konstrukt-und die Rückkehr derCompletableFuture
sofort, und rufen Siecomplete(T result)
sobald die Berechnung fertig ist.Werde ich ein Beispiel geben von dem, was Versprechen und wie Sie deren Wert festgelegt werden konnte, zu jeder Zeit, im Gegensatz zur Zukunft, der Wert ist nur lesbar.
Angenommen, Sie haben eine Mutter, und Sie bitten, für Ihr Geld.
Nun , Sie trick Ihre Mutter in erstellen Sie ein Versprechen, die eventuelle Spende, Sie gibt dir das promise-Objekt, aber Sie ist nicht wirklich Ausschlag zu erfüllen, es aber doch:
Sind Sie glücklich, Sie laufen danke, dass Sie Ihre Mutter:
Aber Ihr Vater mischt und in der Regel bricht der Mutter Pläne und rundet das Versprechen (setzt seinen Wert!) mit weit geringeren Beitrag, als Väter es tun, sehr resolut, während Mama langsam öffnete Ihre Handtasche (Hinweis-Thread.sleep(...)) :
Ausgabe ist:
Mutter das Versprechen wurde erstellt , aber er wartete einige "Abschluss" - Veranstaltung.
Du erstellt ein solches Ereignis ein, akzeptieren Ihre Versprechen und kündigt Ihre Pläne zu danken, die Ihre Mutter:
In diesem moment meine Mutter wollte Sie öffnen Ihre Geldbörse...aber sehr langsam...
Vater und mischte sich viel schneller abgeschlossen und die Versprechen, anstatt Ihre Mutter:
Haben Sie bemerkt, ein Testamentsvollstrecker, dass ich schrieb explizit?
Interessant ist, dass, wenn Sie verwenden Sie die Standard-implizite Testamentsvollstrecker statt (commonPool) und Vater ist nicht zu Hause, nur die Mutter mit Ihrem "slow Hand", dann Ihr Versprechen wird erst dann beendet, wenn das Programm lebt mehr Zeit als Mama braucht man Geld aus dem Geldbeutel. Ich meine default-executor Handlungen in einer Weise von "daemon". Ich habe nicht gefunden, eine gute Beschreibung dieser Tatsache...
Nicht sicher, ob dies kann eine Antwort sein, aber so wie ich das sehe, was andere gesagt haben, jemand kann es so Aussehen, wie Sie müssen zwei separate Abstraktionen für diese beiden Konzepte, so dass einer von Ihnen (
Future
) ist nur eine schreibgeschützte Ansicht der anderen (Promise
) ... aber eigentlich ist das nicht nötig.Beispielsweise anschauen, wie Versprechungen sind definiert in javascript:
https://promisesaplus.com/
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Der Fokus ist auf die Kombinierbarkeit mit der
then
Methode wie:sodass der asynchrone Berechnung zu schauen, wie synchron:
was ziemlich cool ist.
(Nicht so cool wie async-await aber async-await entfernt nur die vorformulierten ....then(function(result) {.... von es).
Und tatsächlich Ihre Abstraktion ist ziemlich gut, wie das Versprechen Konstruktor
können Sie zwei Rückrufe können verwendet werden, um entweder das
Promise
erfolgreich oder mit einem Fehler. So, dass nur der code, der erstellt diePromise
abgeschlossen werden kann und der code, der erhält eine bereits konstruiertePromise
Objekt den nur-lese-Ansicht.Mit Vererbung die oben erreicht werden kann, wenn beheben und ablehnen sind geschützte Methoden.
CompletableFuture
vielleicht haben einige ähnlichkeit mit einerPromise
aber es ist noch nicht einPromise
, weil die Art und Weise ist es zum Verzehr bestimmt ist das anders: einPromise
's Ergebnis verbraucht wird durch den Aufrufthen(function)
, und die Funktion wird ausgeführt im Zusammenhang mit den Produzent sofort, nachdem der Produzent fordertresolve
. EinFuture
's Ergebnis verbraucht wird durch den Aufrufget
die Ursachen der consumer-thread solange warten, bis der Erzeuger-thread erzeugt wurde, den Wert, dann verarbeitet es in der Verbraucher.Future
ist von sich aus multithreaded, aber...Promise
mit nur einem einzigen thread (und in der Tat ist die genaue Umgebung, in die Sie ursprünglich entwickelt wurden für: javascript-Anwendungen in der Regel nur über einen einzigen thread, so dass Sie nicht implementierenFuture
dort).Promise
ist daher viel leichter und effizienter alsFuture
, aberFuture
kann hilfreich sein in Situationen, die komplexer und erfordern die Zusammenarbeit zwischen threads, die können nicht einfach angeordnet werden, durch die VerwendungPromise
s. Um es zusammenzufassen:Promise
ist ein push-Modell, währendFuture
ist ein pull-Modell (cf-Iterierbar vs Beobachtbaren)XMLHttpRequest
). Ich glaube nicht, dass die Effizienz behaupten, Sie haben zufällig ein paar zahlen? +++ Das heißt, eine sehr schöne Erklärung.get
auf eine ungelösteFuture
wird notwendigerweise auch mit der 2 thread context switches, die mindestens ein paar Jahre zurück, war wahrscheinlich rund 50 us.Keine set-Methode in Zukunft eine Schnittstelle, nur get-Methode, so ist es schreibgeschützt.
Über CompletableFuture, dieser Artikel vielleicht hilfreich.
completablefuture
Für client-code, das Versprechen ist für die Beobachtung oder das anbringen callback, wenn ein Ergebnis vorhanden ist, in der Erwägung, dass die Zukunft ist zu warten, für das Ergebnis und dann weiter. Theoretisch alles was möglich ist zu tun mit futures was kann getan werden, mit Versprechungen, aber aufgrund der Stil Unterschied, der daraus resultierende API für zusagen, die in verschiedenen Sprachen machen die Verkettung einfacher.