Tanto los futuros como las promesas se bloquean hasta que han calculado sus valores, entonces, ¿cuál es la diferencia entre ellos?
Tanto los futuros como las promesas se bloquean hasta que han calculado sus valores, entonces, ¿cuál es la diferencia entre ellos?
Respuestas:
Respondiendo en términos de Clojure, aquí hay algunos ejemplos del screencast de Sean Devlin :
(def a-promise (promise))
(deliver a-promise :fred)
(def f (future (some-sexp)))
(deref f)
Tenga en cuenta que en la promesa está entregando explícitamente un valor que selecciona en un cálculo posterior ( :fred
en este caso). El futuro, en cambio, se consume en el mismo lugar donde se creó. Se some-expr
presume que se lanza detrás de escena y se calcula en tándem (eventualmente), pero si permanece sin evaluar en el momento en que se accede a los bloques de hilo hasta que esté disponible.
editado para agregar
Para ayudar a distinguir mejor entre una promesa y un futuro, tenga en cuenta lo siguiente:
promise
. Ese objeto de promesa ahora se puede pasar a cualquier hilo.deliver
enviar los resultados a ese objeto de promesa.deref
cumplir su promesa antes de que haya terminado con su cálculo se bloqueará hasta que haya terminado. Una vez que haya terminado y haya deliver
editado la promesa, la promesa ya no se bloqueará.deref
el futuro. Si el cálculo ya se completó, obtendrá los resultados. Si aún no se ha completado, bloquea hasta que lo haya hecho. (Es de suponer que si aún no ha comenzado, deref
significa que comienza a ejecutarse, pero esto tampoco está garantizado).Si bien podría hacer que la expresión en el futuro sea tan complicada como el código que sigue a la creación de una promesa, es dudoso que sea deseable. Esto significa que los futuros son realmente más adecuados para cálculos rápidos y en segundo plano, mientras que las promesas son realmente más adecuadas para rutas de ejecución grandes y complicadas. Además, las promesas parecen, en términos de cálculos disponibles, un poco más flexibles y orientadas hacia el creador de la promesa que hace el trabajo y otro hilo que cosecha la cosecha. Los futuros están más orientados a iniciar automáticamente un hilo (sin la sobrecarga fea y propensa a errores) y continuar con otras cosas hasta que usted, el hilo de origen, necesite los resultados.
future
llamada puede incluir N sexprs.
Tanto Future como Promise son mecanismos para comunicar el resultado de la computación asincrónica del Productor al Consumidor (es).
En el caso de Future, el cálculo se define en el momento de la creación de Future y la ejecución asíncrona comienza "lo antes posible". También "sabe" cómo generar un cálculo asincrónico.
En el caso de Promise, el cálculo , su hora de inicio y la invocación asincrónica [posible] se desacoplan del mecanismo de entrega. Cuando el resultado del cálculo está disponible, el Productor debe llamar deliver
explícitamente, lo que también significa que el Productor controla cuándo el resultado está disponible.
Para promesas, Clojure comete un error de diseño al usar el mismo objeto (resultado de la promise
llamada) para producir ( deliver
) y consumir ( deref
) el resultado del cálculo . Estas son dos capacidades muy distintas y deben tratarse como tales.
promise
sería conveniente acoplar la seguridad a un tipo de referencia tan simple (consulte su impl) como es. Los consumidores "malvados" son raros; nada le impide construir su propia abstracción sobre las promesas.
(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))))
Ya hay respuestas excelentes, así que solo agregue el resumen "cómo usar":
Ambos
Crear promesa o futuro devuelve una referencia de inmediato. Esta referencia se bloquea en @ / deref hasta que otro hilo proporcione el resultado del cálculo.
Futuro
Al crear el futuro, proporcionas un trabajo sincrónico por hacer. Se ejecuta en un hilo del grupo ilimitado dedicado.
Promesa
No das argumentos al crear una promesa. La referencia debe pasarse a otro hilo de 'usuario' que será deliver
el resultado.
En Clojure, promise
, future
, y delay
son promesa como objetos. Todos representan un cálculo que los clientes pueden esperar usando deref
(o @
). Los clientes reutilizan el resultado para que el cálculo no se ejecute varias veces.
Se diferencian en la forma en que se realiza el cálculo:
future
iniciará el cálculo en un hilo de trabajo diferente. deref
se bloqueará hasta que el resultado esté listo.
delay
realizará el cálculo de forma perezosa, cuando el primer cliente utilice deref
, o force
.
promise
ofrece la mayor flexibilidad, ya que su resultado se entrega de forma personalizada mediante el uso de deliver
. Lo usa cuando ninguno de los dos future
o delay
coincide con su caso de uso.
En primer lugar, a Promise
es a Future
. Creo que quieres saber la diferencia entre a Promise
y a FutureTask
.
A Future
representa un valor que no se conoce actualmente pero que se conocerá en el futuro.
A FutureTask
representa el resultado de un cálculo que ocurrirá en el futuro (tal vez en algún grupo de subprocesos). Cuando intentas acceder al resultado, si el cálculo aún no se ha realizado, se bloquea. De lo contrario, el resultado se devuelve de inmediato. No hay ninguna otra parte involucrada en el cálculo del resultado, ya que usted especifica el cálculo de antemano.
A Promise
representa un resultado que el prometidor entregará al prometido en el futuro. En este caso, usted es el prometido y el prometedor es el que le dio el Promise
objeto. De manera similar a FutureTask
, si intenta acceder al resultado antes de que Promise
se haya cumplido, se bloqueará hasta que el prometedor cumpla con el Promise
. Una vez Promise
cumplido el, obtienes el mismo valor siempre e inmediatamente. A diferencia de a FutureTask
, hay otra parte involucrada aquí, una que hizo el Promise
. Que otra parte es responsable de hacer el cálculo y cumplir con el Promise
.
En ese sentido, una FutureTask
es una que Promise
te hiciste a ti mismo.