Sia i futures che le promesse si bloccano fino a quando non hanno calcolato i loro valori, quindi qual è la differenza tra loro?
Sia i futures che le promesse si bloccano fino a quando non hanno calcolato i loro valori, quindi qual è la differenza tra loro?
Risposte:
Rispondendo in termini di Clojure, ecco alcuni esempi dallo screencast di Sean Devlin :
(def a-promise (promise))
(deliver a-promise :fred)
(def f (future (some-sexp)))
(deref f)
Si noti che nella promessa si fornisce esplicitamente un valore selezionato in un calcolo successivo ( :fred
in questo caso). Il futuro, invece, si consuma nello stesso luogo in cui è stato creato. Il some-expr
è presumibilmente lanciato dietro le quinte e calcolato in tandem (eventualmente), ma se rimane non valutata dal tempo si accede al blocchi di filettatura finché non è disponibile.
modificato per aggiungere
Per aiutare a distinguere ulteriormente tra una promessa e un futuro, nota quanto segue:
promise
. Quell'oggetto promessa può ora essere passato a qualsiasi thread.deliver
i risultati di quell'oggetto promesso.deref
mantenere la tua promessa prima che tu abbia finito con il tuo calcolo si bloccherà finché non avrai finito. Una volta che hai finito e hai modificato deliver
la promessa, la promessa non si bloccherà più.deref
il futuro. Se il calcolo è già stato completato, ne ottieni i risultati. Se non è già stato completato, blocchi finché non lo ha fatto. (Presumibilmente, se non è ancora iniziato, deref
significa che inizia l'esecuzione, ma anche questo non è garantito.)Anche se in futuro potresti rendere l'espressione complicata come il codice che segue la creazione di una promessa, è dubbio che sia desiderabile. Ciò significa che i futures sono davvero più adatti a calcoli rapidi e in background, mentre le promesse sono davvero più adatte a percorsi di esecuzione ampi e complicati. Inoltre, le promesse sembrano, in termini di calcoli disponibili, un po 'più flessibili e orientate verso il creatore della promessa che fa il lavoro e un altro filo che raccoglie il raccolto. I futuri sono più orientati verso l'avvio automatico di un thread (senza il sovraccarico brutto e soggetto a errori) e andare avanti con altre cose fino a quando tu - il thread di origine - hai bisogno dei risultati.
future
chiamata può includere N sexprs.
Sia Future che Promise sono meccanismi per comunicare il risultato del calcolo asincrono dal produttore al consumatore (i).
In caso di Future, il calcolo è definito al momento della creazione di Future e l'esecuzione asincrona inizia "ASAP". Inoltre "sa" come generare un calcolo asincrono.
In caso di Promise, il calcolo , la sua ora di inizio e [possibile] invocazione asincrona sono disaccoppiati dal meccanismo di consegna. Quando il risultato del calcolo è disponibile, Producer deve chiamare deliver
esplicitamente, il che significa anche che Producer controlla quando risultato diventa disponibile.
For PromisesClojure commette un errore di progettazione utilizzando lo stesso oggetto (risultato della promise
chiamata) sia per produrre ( deliver
) che per consumare ( deref
) il risultato del calcolo . Queste sono due capacità molto distinte e dovrebbero essere trattate come tali.
promise
sarebbe conveniente. I consumatori "cattivi" sono rari; niente ti impedisce di costruire la tua astrazione in cima alle promesse.
(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))))
Ci sono già ottime risposte quindi aggiungendo solo il riepilogo "come usare":
Tutti e due
La creazione di promesse o future restituisce immediatamente un riferimento. Questo riferimento si blocca su @ / deref finché il risultato del calcolo non viene fornito da un altro thread.
Futuro
Quando crei il futuro, fornisci un lavoro sincrono da fare. Viene eseguito in un thread dal pool illimitato dedicato.
Promettere
Non dai argomenti quando crei una promessa. Il riferimento dovrebbe essere passato ad un altro thread "utente" che ne darà deliver
il risultato.
In Clojure, promise
, future
, e delay
sono promessa come oggetti. Rappresentano tutti un calcolo che i client possono attendere utilizzando deref
(o @
). I client riutilizzano il risultato, in modo che il calcolo non venga eseguito più volte.
Differiscono nel modo in cui viene eseguito il calcolo:
future
inizierà il calcolo in un diverso thread di lavoro. deref
si bloccherà fino a quando il risultato non sarà pronto.
delay
eseguirà il calcolo pigramente, quando il primo client usa deref
, o force
.
promise
offre la massima flessibilità, poiché il risultato viene fornito in qualsiasi modo personalizzato utilizzando deliver
. Lo usi quando nessuno dei due future
o delay
corrisponde al tuo caso d'uso.
In primo luogo, a Promise
è a Future
. Penso che tu voglia conoscere la differenza tra a Promise
e a FutureTask
.
A Future
rappresenta un valore che non è attualmente noto ma lo sarà in futuro.
A FutureTask
rappresenta il risultato di un calcolo che avverrà in futuro (forse in qualche pool di thread). Quando si tenta di accedere al risultato, se il calcolo non è ancora avvenuto, si blocca. In caso contrario, il risultato viene restituito immediatamente. Non ci sono altre parti coinvolte nel calcolo del risultato poiché il calcolo è stato specificato in anticipo.
A Promise
rappresenta un risultato che verrà consegnato dal promettente al promesso in futuro. In questo caso tu sei il promesso e il promettente è colui che ti ha dato l' Promise
oggetto. Simile a FutureTask
, se si tenta di accedere al risultato prima che Promise
sia stato soddisfatto, viene bloccato fino a quando il promettente non soddisfa il Promise
. Una volta Promise
soddisfatto, ottieni sempre e immediatamente lo stesso valore. A differenza di a FutureTask
, qui è coinvolta un'altra parte, che ha creato il file Promise
. Che un'altra parte sia responsabile per il calcolo e l'adempimento del Promise
.
In questo senso, a FutureTask
è un Promise
fatto a te stesso.