如何清楚地构建core.async通道之间的依赖关系?

时间:2015-11-11 21:18:49

标签: clojure core.async

假设我有一个计算语料库,我想使用core.async异步运行,但不幸的是,一些函数依赖于其他函数的输出。如何在我的代码中干净地构建这个,同时获得最佳性能?

我遇到的一些潜在解决方案是

  • Prismatic's Graph - 看起来很合理,虽然我没有用core.async频道测试它;事实上,它需要使用fnk对我来说有点不利,因为它需要购买他们的DSL用于函数定义,但如果这是最好的解决方案,那么我不介意。
  • Javelin cells - 仅针对ClojureScript(当前)并使用FRP而不是CSP作为实现,但它通过公式单元在计算之间建立依赖关系方面做得非常好。
  • Onyx - 用于分布式计算(作为Apache Storm的竞争对手等),但具有“工作流”抽象,处理计算之间的依赖关系并与core.async一起使用。这似乎最适合我的问题域,但我不确定是否需要所有集群管理功能的开销。

这个问题的规范解决方案是什么?

编辑:添加了Onyx

3 个答案:

答案 0 :(得分:2)

这个问题很难回答,因为你的问题缺乏关于你的用例的具体细节。像Graph,Javelin和Onyx这样的库都有不同的用例,不仅仅是让计算相互依赖。

如果您只想根据系统另一部分生成的结果获得一个线程或阻止块,我建议只使用core.async原语而不需要任何其他库。

使执行等待另一个活动线程的最基本解决方案是在从通道获取值时使用阻塞。当该通道上没有值可用时,这将停止线程(或阻止)。

正如您在下面的示例中所看到的,进行计算取决于在另一个线程中完成的活动非常容易。

(let [c (chan)]
  (thread (>!! c “hello”))
  (assert (= “hello” (<!! c)))
  (close! c)

还有更复杂的机制可供选择。 Alts!!函数提供了同时在多个通道上等待的功能。 pipeline函数的几种不同风格允许您以类似方式对数据流中的并发进行建模。

是否存在任何无法使用内置函数清楚表达的特定问题?

答案 1 :(得分:1)

我不认为有一种规范的方法可以解决它,core.async是如此新颖,很少有人给它一个机会。如果我选择我的三个选项,我会使用Graph,它已经在生产中部署和测试了一段时间,而且你不需要Clojurescript来运行它。如果您对FRP解决方案感兴趣,请查看Java Reactive ExtensionsRxClojure中存在Clojure绑定。

答案 2 :(得分:0)

对于上述#3,onyx-local-rt可能符合要求:

  

onyx-local-rt是Onyx的替代运行时,它在   纯粹的确定性环境。该运行时仅在本地运行,并且   不以分布式模式运行。这是一个孵化库,   意味着该代码将在以后移入Onyx内核。