Future vs Thread:哪个更适合在 core.async 中使用通道



使用频道时,是建议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 应该可以随意以对它们最有意义的方式启动线程。

threadfuture之间的差异

正如您引用的 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/threadfuture 之间的主要区别在于:

  • thread 将返回一个通道,该通道只允许您在获得 nil 之前从通道take!一次,如果您需要通道语义,这很好,但如果您想一遍又一遍地使用该结果,则不理想
  • 相比之下,future 返回一个可 deeffable 对象,一旦线程完成,每次deref时都会返回答案,当您想要多次获取此结果 很方便,但这是以通道语义为代价的

如果要保留通道语义,可以使用async/thread并将结果放在(并返回a)async/promise-chan上,一旦有值,它将始终在以后take!返回该值。这比仅仅调用future稍微多一点,因为您必须将结果显式放置在promise-chan上并返回它而不是thread通道,但可以为您购买与其余core.async基础架构的互操作性。

这几乎让人怀疑是否不应该有一个core.async/thread-promisecore.async/go-promise来使这更方便......

最新更新