简体   繁体   English

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

[英]Future vs Thread: Which is better for working with channels in core.async?

When working with channels, is future recommended or is thread ?使用渠道时,是future推荐还是thread Are there times when future makes more sense?是否有future更有意义的时候?

Rich Hickey's blog post on core.async recommends using thread rather than future : Rich Hickey 关于 core.async 的博客文章建议使用thread而不是future

While you can use these operations on threads created with eg future, there is also a macro, thread , analogous to go, that will launch a first-class thread and similarly return a channel, and should be preferred over future for channel work.虽然您可以在使用例如 future 创建的线程上使用这些操作,但还有一个宏 thread ,类似于 go,它将启动一个一流的线程并类似地返回一个通道,并且应该优先于 future 进行通道工作。

~ http://clojure.com/blog/2013/06/28/clojure-core-async-channels.html ~ http://clojure.com/blog/2013/06/28/clojure-core-async-channels.html

However, a core.async example makes extensive use of future when working with channels:但是,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 ~ https://github.com/clojure/core.async/blob/master/examples/ex-async.clj

Summary 摘要

In general, thread with its channel return will likely be more convenient for the parts of your application where channels are prominent. 通常,具有通道返回的thread对于通道突出的应用程序部分可能更方便。 On the other hand, any subsystems in your application that interface with some channels at their boundaries but don't use core.async internally should feel free to launch threads in whichever way makes the most sense for them. 另一方面,应用程序中与其边界处的某些通道接口但未在内部使用core.async的任何子系统都可以随意以最适合它们的方式启动线程。

Differences between thread and future threadfuture之间的差异

As pointed out in the fragment of the core.async blog post you quote, thread returns a channel, just like go : 正如您引用的core.async博客文章的片段中所指出的, thread返回一个频道,就像go

(let [c (thread :foo)]
  (<!! c))
;= :foo

The channel is backed by a buffer of size 1 and will be closed after the value returned by the body of the thread form is put on it. 该通道由大小为1的缓冲区支持,并且在将thread表的主体返回的值放在其上之后将关闭。 (Except if the returned value happens to be nil , in which case the channel will be closed without anything being put on it -- core.async channels do not accept nil .) (除非返回的值恰好是nil ,在这种情况下,通道将关闭而不会放置任何内容 - core.async通道不接受nil 。)

This makes thread fit in nicely with the rest of core.async. 这使得thread非常适合core.async的其余部分。 In particular, it means that go + the single-bang ops and thread + the double-bang ops really are used in the same way in terms of code structure, you can use the returned channel in alt! 特别是,它意味着go +单声道操作和thread +双重操作在代码结构方面确实以相同的方式使用,你可以在alt!使用返回的通道alt! / alts! /等alts! (and the double-bang equivalents) and so forth. (和双重等价物)等等。

In contrast, the return of future can be deref 'd ( @ ) to obtain the value returned by the future form's body (possibly nil ). 相比之下, future的回报可以是deref@ )来获得future形式的主体返回的值(可能是nil )。 This makes future fit in very well with regular Clojure code not using channels. 这使得future非常适合使用不使用通道的常规Clojure代码。

There's another difference in the thread pool being used -- thread uses a core.async-specific thread pool, while future uses one of the Agent-backing pools. 正在使用的线程池还有另一个不同之处 - thread使用特定于core.async的线程池,而future使用其中一个代理支持池。

Of course all the double-bang ops, as well as put! 当然所有的双重操作,以及put! and take! take! , work just fine regardless of the way in which the thread they are called from was started. ,无论从哪个线程调用它们的方式开始,都可以正常工作。

it sounds like he is recommending using core. 听起来他建议使用核心。 async's built in thread macro rather than java's Thread class. async的内置线程宏而不是java的Thread类。

http://clojure.github.io/core.async/#clojure.core.async/thread http://clojure.github.io/core.async/#clojure.core.async/thread

Aside from which threadpool things are run in (as pointed out in another answer), the main difference between async/thread and future is this:除了在哪个线程池中运行(如另一个答案中所指出的)之外, async/threadfuture之间的主要区别在于:

  • thread will return a channel which only lets you take! thread将返回一个只让你take!的频道take! from the channel once before you just get nil, so good if you need channel semantics, but not ideal if you want to use that result over and over在你得到 nil 之前从通道一次,如果你需要通道语义,那么好,但如果你想一遍又一遍地使用该结果,那就不理想了
  • in contrast, future returns a dereffable object, which once the thread is complete will return the answer every time you deref , making it convenient when you want to get this result more than once, but this comes at the cost of channel semantics相比之下, future返回一个 derefable 对象,一旦线程完成,每次deref都会返回答案,这在您想要多次获得此结果时很方便,但这是以通道语义为代价的

If you want to preserve channel semantics, you can use async/thread and place the result on (and return a) async/promise-chan , which, once there's a value, will always return that value on later take!如果您想保留通道语义,您可以使用async/thread并将结果放在(并返回) async/promise-chan上,一旦有值,它将始终在以后返回该值take! s. s。 It's slightly more work than just calling future , since you have to explicitly place the result on the promise-chan and return it instead of the thread channel, but buys you interoperability with the rest of the core.async infrastructure.它比只调用future稍微多一些工作,因为您必须明确地将结果放在promise-chan并返回它而不是thread通道,但是为您购买了与core.async基础结构其余部分的互操作性。

It almost makes one wonder if there shouldn't be a core.async/thread-promise and core.async/go-promise to make this more convenient...这几乎让人怀疑是否不应该有一个core.async/thread-promisecore.async/go-promise来使这更方便......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM