使用频道时,是建议future
还是thread
?有没有future
更有意义的时候?
Rich Hickey在core.async上的博客文章建议使用thread
而不是future
:
虽然您可以在使用 future 创建的线程上使用这些操作,但也有一个宏 线程 ,类似于 go,它将启动一个一流的线程并类似地返回一个通道,并且应该优先于 future 进行通道工作。
~ http://clojure.com/blog/2013/06/28/clojure-core-async-channels.html
但是,core.async 示例在使用通道时广泛使用future
:
(defn fake-search [kind]
(fn [c query]
(future
(<!! (timeout (rand-int 100)))
(>!! c [kind query]))))
~ https://github.com/clojure/core.async/blob/master/examples/ex-async.clj
总结
通常,thread
及其通道返回对于通道突出的应用程序部分可能更方便。另一方面,应用程序中的任何子系统在其边界处与某些通道交互,但在内部不使用 core.async 应该可以随意以对它们最有意义的方式启动线程。
thread
和future
之间的差异
正如您引用的 core.async 博客文章片段中指出的那样,thread
返回一个通道,就像 go
一样:
(let [c (thread :foo)]
(<!! c))
;= :foo
该通道由大小为 1 的缓冲区支持,并在将 thread
窗体的主体返回的值放在其上后关闭。(除非返回值恰好是nil
,在这种情况下,通道将被关闭而不在其上放置任何东西 - core.async 通道不接受nil
。
这使得thread
很好地适应了core.async的其余部分。特别是,这意味着go
+ 单爆炸运算和thread
+ 双爆炸运算在代码结构方面确实以相同的方式使用,你可以在 alt!
/alts!
中使用返回的通道(以及双爆炸等效项)等等。
相反,future
的返回可以deref
(@
)来获得future
表单的主体返回的值(可能是nil
)。这使得future
非常适合不使用通道的常规 Clojure 代码。
使用的线程池还有另一个区别 - thread
使用特定于 core.async 的线程池,而future
使用代理支持池之一。
当然,所有的双爆炸操作,以及 put!
和 take!
,无论调用它们的线程以何种方式启动,都可以正常工作。
听起来他建议使用core。 async的内置线程宏而不是Java的Thread类。
http://clojure.github.io/core.async/#clojure.core.async/thread
哪个线程池中运行内容(如另一个答案中指出的那样),async/thread
和 future
之间的主要区别在于:
-
thread
将返回一个通道,该通道只允许您在获得 nil 之前从通道take!
一次,如果您需要通道语义,这很好,但如果您想一遍又一遍地使用该结果,则不理想 - 相比之下,
future
返回一个可 deeffable 对象,一旦线程完成,每次deref
时都会返回答案,当您想要多次获取此结果时 很方便,但这是以通道语义为代价的
如果要保留通道语义,可以使用async/thread
并将结果放在(并返回a)async/promise-chan
上,一旦有值,它将始终在以后take!
返回该值。这比仅仅调用future
稍微多一点,因为您必须将结果显式放置在promise-chan
上并返回它而不是thread
通道,但可以为您购买与其余core.async
基础架构的互操作性。
这几乎让人怀疑是否不应该有一个core.async/thread-promise
和core.async/go-promise
来使这更方便......