Zarówno kontrakty terminowe, jak i obietnice blokują się, dopóki nie obliczą swoich wartości, więc jaka jest różnica między nimi?
clojure
terminology
future
promise
appshare.co
źródło
źródło
Odpowiedzi:
Odpowiadając w kategoriach Clojure, oto kilka przykładów z screencastu Seana Devlina :
(def a-promise (promise)) (deliver a-promise :fred) (def f (future (some-sexp))) (deref f)
Zwróć uwagę, że w obietnicy jawnie podajesz wartość wybraną w późniejszych obliczeniach (
:fred
w tym przypadku). Natomiast przyszłość konsumowana jest w tym samym miejscu, w którym została stworzona. Prawdopodobniesome-expr
jest uruchamiany za kulisami i obliczany w tandemie (ostatecznie), ale jeśli pozostaje nieoceniony do czasu uzyskania dostępu do bloków wątku, dopóki nie będzie dostępny.edytowane, aby dodać
Aby lepiej odróżnić obietnicę od przyszłości, zwróć uwagę na następujące kwestie:
obietnica
promise
. Ten obiekt obietnicy można teraz przekazać do dowolnego wątku.deliver
wyniki do tego obiektu obietnicy.deref
spełnić twoją obietnicę, zanim zakończysz obliczenia, zostanie zablokowany, dopóki nie skończysz. Gdy skończysz ideliver
zrealizujesz obietnicę, obietnica nie będzie już blokowana.przyszłość
deref
przyszłością. Jeśli obliczenia zostały już zakończone, otrzymasz ich wyniki. Jeśli jeszcze się nie zakończył, blokujesz, dopóki się nie skończy. (Przypuszczalnie jeśli jeszcze się nie rozpoczął,deref
oznacza to, że zaczyna się uruchamiać, ale to również nie jest gwarantowane).Podczas mógł dokonać wyraz w przyszłości tak skomplikowane jak kod, który następuje utworzenie obietnicy, to wątpliwe, że to pożądane. Oznacza to, że kontrakty futures są bardziej odpowiednie do szybkich, opartych na tle obliczeń, podczas gdy obietnice są bardziej odpowiednie dla dużych, skomplikowanych ścieżek realizacji. Również obietnice wydają się, jeśli chodzi o dostępne obliczenia, nieco bardziej elastyczne i zorientowane na twórcę obietnic wykonującego pracę i kolejny wątek zbierający plony. Futures są bardziej zorientowane na automatyczne uruchamianie wątku (bez brzydkiego i podatnego na błędy narzutu) i kontynuowanie innych rzeczy, dopóki Ty - początkowy wątek - nie będziesz potrzebować wyników.
źródło
future
przypomnienia, treść rozmowy może zawierać N seksprów.Zarówno Future, jak i Promise to mechanizmy do przekazywania wyników obliczeń asynchronicznych od producenta do konsumenta (-ów).
W przypadku Future obliczenie jest zdefiniowany w momencie tworzenia przyszłości i asynchroniczne wykonanie zaczyna „ASAP”. „Wie” również, jak utworzyć obliczenia asynchroniczne.
W przypadku Obietnicy obliczenie jego czas rozpoczęcia i [możliwe] asynchroniczny wywołania są oddzielone od mechanizmu wprowadzającego. Gdy wynik obliczenia jest dostępny, producent musi wywołać
deliver
jawne wywołanie , co oznacza również, że producent kontroluje, kiedy wynik staje się dostępny.W przypadku Promises Clojure popełnia błąd projektowy, używając tego samego obiektu (wyniku
promise
wywołania) zarówno do wyprodukowania (deliver
), jak i do skonsumowania (deref
) wyniku obliczeń . Są to dwie bardzo różne możliwości i tak należy je traktować.źródło
promise
byłoby wygodne. „Zli” konsumenci są rzadkością; nic nie powstrzymuje Cię przed budowaniem własnej abstrakcji oprócz obietnic.(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))))
Istnieją już doskonałe odpowiedzi, więc wystarczy dodać podsumowanie „jak korzystać”:
Obie
Tworzenie obietnicy lub przyszłości natychmiast zwraca odniesienie. To odniesienie blokuje @ / deref, dopóki inny wątek nie dostarczy wyniku obliczeń.
Przyszłość
Tworząc przyszłość, zapewniasz synchroniczne zadanie do wykonania. Jest wykonywany w wątku z dedykowanej puli nieograniczonej.
Obietnica
Tworząc obietnicę, nie podajesz żadnych argumentów. Odwołanie powinno zostać przekazane do innego wątku „użytkownika”, który da
deliver
wynik.źródło
W Clojure,
promise
,future
, idelay
to obietnica przedmiotów podobnych. Wszystkie reprezentują obliczenia, na które klienci mogą czekać, używającderef
(lub@
). Klienci ponownie wykorzystują wynik, aby obliczenia nie były wykonywane kilka razy.Różnią się sposobem wykonywania obliczeń:
future
rozpocznie obliczenia w innym wątku roboczym.deref
będzie blokować, aż wynik będzie gotowy.delay
wykona obliczenia leniwie, gdy pierwszy klient użyjederef
lubforce
.promise
oferuje największą elastyczność, ponieważ jego wynik jest dostarczany w dowolny niestandardowy sposób za pomocądeliver
. Używasz go, gdy żadenfuture
lubdelay
pasuje do twojego przypadku użycia.źródło
Po pierwsze, a
Promise
jestFuture
. Myślę, że chcesz poznać różnicę między aPromise
i aFutureTask
.A
Future
reprezentuje wartość, która nie jest obecnie znana, ale będzie znana w przyszłości.A
FutureTask
reprezentuje wynik obliczenia, które nastąpi w przyszłości (może w jakiejś puli wątków). Kiedy próbujesz uzyskać dostęp do wyniku, jeśli obliczenia jeszcze się nie wydarzyły, blokuje się. W przeciwnym razie wynik jest zwracany natychmiast. Żadna inna strona nie jest zaangażowana w obliczanie wyniku, ponieważ obliczenia zostały określone przez Ciebie z góry.A
Promise
reprezentuje wynik, który zostanie przekazany przez przyrzeczonego przyrzeczonemu w przyszłości. W tym przypadku jesteś obiecującym, a obiecującym jest ten, który dał ciPromise
przedmiot. Podobnie jak wFutureTask
przypadku, jeśli spróbujesz uzyskać dostęp do wyniku, zanimPromise
zostanie spełniony, zostanie on zablokowany, dopóki obiecujący nie spełni warunkuPromise
. PoPromise
spełnieniu warunku zawsze i natychmiast otrzymujesz tę samą wartość. W przeciwieństwie do aFutureTask
, jest tu zaangażowana inna strona, która sprawiła, żePromise
. Ta inna strona jest odpowiedzialna za wykonanie obliczeń i wypełnieniePromise
.W tym sensie a
FutureTask
toPromise
ty stworzone dla siebie.źródło