期货和承诺都会阻止,直到他们计算出它们的价值,那么它们之间有什么区别呢?
答案 0 :(得分:50)
回答Clojure术语,这里有一些来自Sean Devlin's screencast的例子:
(def a-promise (promise))
(deliver a-promise :fred)
(def f (future (some-sexp)))
(deref f)
请注意,在承诺中,您明确提供了在稍后的计算中选择的值(在本例中为:fred
)。另一方面,未来正在被创造的同一个地方消费。 some-expr
可能是在幕后启动并串联计算(最终),但如果在访问它时它仍未被评估,则线程会阻塞直到它可用。
已编辑以添加
为了进一步区分承诺和未来,请注意以下事项:
promise
。该promise对象现在可以传递给任何线程。deliver
将结果发送到该承诺对象。deref
您的承诺的任何项目都会阻止,直到您完成为止。一旦你完成并且deliver
承诺,承诺将不再阻止。deref
是未来。如果计算已经完成,您将获得结果。如果尚未完成,则阻止直至完成。 (大概如果还没有开始,deref
意味着它开始执行,但这也不能保证。)虽然你可以使表达在将来像创建一个承诺之后的代码一样复杂,但是这是值得怀疑的。这意味着期货更适合快速,可进行背景的计算,而承诺更适合于大型,复杂的执行路径。在可用的计算方面,承诺似乎更加灵活,并且面向承诺创造者完成工作,另一个线索收获丰收。期货更倾向于自动启动一个线程(没有丑陋和容易出错的开销)并继续其他事情,直到你 - 原始线程 - 需要结果。
答案 1 :(得分:23)
Future和Promise都是将生产者与消费者之间的异步计算结果进行通信的机制。
在 Future 的情况下,计算在创建Future时定义,异步执行开始“ASAP”。它还“知道”如何产生异步计算。
如果承诺 计算,其开始时间和[可能] 异步调用将与传递机制分离。当计算结果可用时,生产者必须明确调用deliver
,这也意味着当结果可用时,生产者控制。
对于 Promises Clojure通过使用相同的对象(promise
调用的结果)来产生(deliver
)和消耗(deref
)结果,从而导致设计错误计算。这是两个截然不同的能力,应该这样对待。
答案 2 :(得分:2)
已经有很好的答案,所以只添加“如何使用”摘要:
<强>两个强>
创建承诺或将来立即返回引用。该引用在@ / deref上阻塞,直到其他线程提供计算结果。
<强>未来强>
创建未来时,您需要提供同步作业。它是在专用的无界池中的一个线程中执行的。
<强>无极强>
创建承诺时不提供任何参数。该引用应该传递给deliver
结果的其他“用户”线程。
答案 3 :(得分:1)
在Clojure中,promise
,future
和delay
是类似诺言的对象。它们都表示客户端可以使用deref
(或@
)等待的计算。客户端重复使用结果,因此计算不会多次运行。
它们的计算方式不同:
future
将在其他工作线程中启动计算。 deref
将阻塞直到结果准备就绪。
delay
将在第一个客户端使用deref
或force
时延迟执行计算。
promise
提供了最大的灵活性,因为其结果可以通过使用deliver
以任何自定义方式进行传递。当future
或delay
都不符合用例时,就使用它。
答案 4 :(得分:0)
我认为 Clojure for the Brave 的第 9 章对 delay
、future
和 promise
之间的区别有最好的解释。
统一这三个概念的想法是:任务生命周期。一个任务可以被认为经历了三个阶段:一个任务被定义,一个任务被执行,一个任务的结果被使用。
某些编程语言(如 JavaScript)具有类似命名的构造(如 JS 的 Promise
),它们将任务生命周期中的几个(或所有)阶段耦合在一起。例如,在 JS 中,如果不为其提供计算其值的函数(任务)或立即使用常量值Promise
对其进行赋值,就不可能构造一个 resolve
对象。>
然而,Clojure 避免了这种耦合,因此它具有三个独立的构造,每个构造对应于任务生命周期中的一个阶段。
delay:
任务定义future
:任务执行promise
:任务结果每个构造都只关心它自己的任务生命周期阶段,而不是其他任何东西,从而解开像 JS 的 Promise
这样的高阶构造并将它们分成适当的部分。
我们现在看到,在 JavaScript 中,Promise
是上面列出的所有三个 Clojure 结构的组合。示例:
const promise = new Promise((resolve) => resolve(6))
让我们分解一下:
resolve(6)
是任务。Promise
本身。请注意在构建 Promise
时您如何已经安排您的任务运行(在某个未指定的时间)。你不能说“让我把它传递给我系统的另一个组件,让它决定什么时候运行这个任务”。Promise
对象中,可以通过then
ing或await
ing获得。没有办法创建一个“空”的承诺结果,稍后由系统中某些未知的部分填写;您必须定义任务并同时安排它执行。PS:Clojure 强加的分离允许这些构造承担如果它们紧密耦合它们将不适合的角色。例如,Clojure promise
已经与任务定义和执行分离,现在可以用作线程之间的传输单元。
答案 5 :(得分:-3)
首先,Promise
是Future
。我想您想知道Promise
和FutureTask
之间的区别。
Future
表示当前未知但将来会知道的值。
FutureTask
表示将来会发生的计算结果(可能在某个线程池中)。当您尝试访问结果时,如果计算尚未发生,则会阻止。否则结果立即返回。由于计算是由您事先指定的,因此没有其他方参与计算结果。
Promise
表示未来承诺人将向承诺人提供的结果。在这种情况下,您是受诺者,而承诺者就是那个给您Promise
对象的人。与FutureTask
类似,如果您在Promise
完成之前尝试访问结果,则会被阻止,直到承销商履行Promise
为止。完成Promise
后,您会立即获得相同的值。与FutureTask
不同,此处涉及另一方,其中一方是Promise
。另一方负责进行计算并完成Promise
。
从这个意义上说,FutureTask
是你自己制作的Promise
。