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?
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?
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 ( :fredw tym przypadku). Natomiast przyszłość konsumowana jest w tym samym miejscu, w którym została stworzona. Prawdopodobnie some-exprjest 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:
promise. Ten obiekt obietnicy można teraz przekazać do dowolnego wątku.deliverwyniki do tego obiektu obietnicy.derefspełnić twoją obietnicę, zanim zakończysz obliczenia, zostanie zablokowany, dopóki nie skończysz. Gdy skończysz i deliverzrealizujesz obietnicę, obietnica nie będzie już blokowana.derefprzyszł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ął, derefoznacza 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.
futureprzypomnienia, 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ć deliverjawne 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 promisewywoł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ć.
promisebył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 deliverwynik.
W Clojure, promise, future, i delayto obietnica przedmiotów podobnych. Wszystkie reprezentują obliczenia, na które klienci mogą czekać, używając deref(lub @). Klienci ponownie wykorzystują wynik, aby obliczenia nie były wykonywane kilka razy.
Różnią się sposobem wykonywania obliczeń:
futurerozpocznie obliczenia w innym wątku roboczym. derefbędzie blokować, aż wynik będzie gotowy.
delaywykona obliczenia leniwie, gdy pierwszy klient użyje dereflub force.
promiseoferuje największą elastyczność, ponieważ jego wynik jest dostarczany w dowolny niestandardowy sposób za pomocą deliver. Używasz go, gdy żaden futurelub delaypasuje do twojego przypadku użycia.
Po pierwsze, a Promisejest Future. Myślę, że chcesz poznać różnicę między a Promisei a FutureTask.
A Futurereprezentuje wartość, która nie jest obecnie znana, ale będzie znana w przyszłości.
A FutureTaskreprezentuje 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 Promisereprezentuje 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ł ci Promiseprzedmiot. Podobnie jak w FutureTaskprzypadku, jeśli spróbujesz uzyskać dostęp do wyniku, zanim Promisezostanie spełniony, zostanie on zablokowany, dopóki obiecujący nie spełni warunku Promise. Po Promisespełnieniu warunku zawsze i natychmiast otrzymujesz tę samą wartość. W przeciwieństwie do a FutureTask, jest tu zaangażowana inna strona, która sprawiła, że Promise. Ta inna strona jest odpowiedzialna za wykonanie obliczeń i wypełnienie Promise.
W tym sensie a FutureTaskto Promisety stworzone dla siebie.