Clojure未来和承诺如何不同?
期货和承诺都会阻止,直到他们计算出它们的价值,那么它们之间的区别是什么?
以Clojure的forms回答,下面是一些来自Sean Devlin的截屏的例子:
(def a-promise (promise)) (deliver a-promise :fred) (def f (future (some-sexp))) (deref f)
请注意,在承诺中,您明确地提供了一个在稍后的计算中select的值(在本例中为:fred
)。 另一方面,未来正在被创造的地方消耗。 some-expr
大概是在幕后推出的,并且最终会一起计算出来,但是如果它在被访问的时候仍然没有被评估的话,这个线程就会被阻塞直到它可用。
编辑添加
为了进一步区分承诺和未来,请注意以下几点:
诺言
- 你创造一个
promise
。 那个promise对象现在可以传递给任何线程。 - 你继续计算。 这些可能是非常复杂的计算,涉及副作用,下载数据,用户input,数据库访问,其他承诺 – 无论你喜欢什么。 代码看起来非常像您的主线代码在任何程序中。
- 完成后,您可以
deliver
结果deliver
给承诺对象。 - 在完成计算之前,任何试图
deref
您的承诺的项目都会阻止,直到完成为止。 一旦你完成了,你已经deliver
了承诺,承诺不会再阻止。
未来
- 你创造你的未来。 你未来的一部分是一个计算expression式。
- 未来可能会或可能不会同时执行。 它可以被分配一个线程,可能来自一个池。 它可以等待,什么都不做。 从你的angular度来看, 你不能说 。
- 在某个时候,你(或者另一个线程)
deref
了未来。 如果计算已经完成,你会得到它的结果。 如果它还没有完成,你会阻止它。 (假设它还没有开始,deref
它意味着它开始执行,但是这也不能保证。)
虽然你可以把未来的expression看作是创造一个承诺之后的代码,但这是值得怀疑的。 这意味着期货真的更适合于快速,可背景的计算,而承诺更适合大型复杂的执行path。 而且,就可用的计算而言,承诺似乎更灵活一点,面向承诺创造者的工作,另一条线索则收获丰收。 期货更倾向于自动启动一个线程(没有丑陋的,易出错的开销),并继续与其他事情,直到你 – 始发线程 – 需要结果。
Future和Promise都是将生产者和消费者之间的asynchronous计算结果进行通信的机制。
在Future的情况下,在Future创build时定义计算 ,asynchronous执行“ASAP”开始。 它也“知道”如何产生一个asynchronous计算。
在Promise 计算的情况下,其开始时间和[可能的] asynchronous调用与传递机制是分离的。 当计算结果可用时,生产者必须显式调用deliver
,这也意味着生产者在结果可用时进行控制。
对Promise Clojure通过使用相同的对象( promise
调用的结果)来产生( deliver
)和消耗( deref
) 计算结果,从而造成devise错误。 这是两种截然不同的能力,应该这样对待。
已经有很好的答案,所以只join“如何使用”总结:
都
创造承诺或未来立即返回一个参考。 这个引用在@ / deref上阻塞,直到计算结果由其他线程提供。
未来
在创造未来时,你需要提供一个同步工作来完成。 它在专用的无界池中执行。
诺言
创造诺言时你没有任何争论。 该引用应该传递给其他“用户”线程,将deliver
结果。
首先,一个Promise
是一个Future
。 我想你想知道Promise
和FutureTask
之间的区别。
“ Future
代表着目前尚不为人知的价值,但将在未来获知。
FutureTask
表示将来会发生的计算结果(也许在某个线程池中)。 当您尝试访问结果时,如果计算尚未发生,则会阻止。 否则结果立即返回。 由于您提前指定了计算,所以没有其他方参与计算结果。
Promise
代表承诺将来承诺者将Promise
的结果。 在这种情况下,你是承诺者,承诺者是那个给你Promise
对象的人。 与FutureTask
类似,如果你在Promise
被实现之前尝试访问结果,它将被阻止,直到Promiser达到Promise
。 一旦Promise
完成,你会立即获得相同的价值。 与“未来任务Promise
不同的是,这里还有另外一个参与方,一个是做出Promise
。 另一方负责计算并履行Promise
。
从这个意义上说, FutureTask
是你自己做出的Promise
。