在clojure core.async go循环中,工作方式的权衡是什么?
随着我编写更多的core.async代码,出现了一种非常常见的模式,即go循环,它在一系列通道上交替,并对消息进行响应,例如:在clojure core.async go循环中,工作方式的权衡是什么?,clojure,core.async,Clojure,Core.async,随着我编写更多的core.async代码,出现了一种非常常见的模式,即go循环,它在一系列通道上交替,并对消息进行响应,例如: (go-loop [state {}] (let [[value task] (alts! tasks)] ...work... (recur state)) 我觉得我不明白我可以用各种方法来完成这项工作,所以我想在这里尝试探索一下 内联或通过调用函数:这会阻止循环继续,直到工作完成。因为它位于go块中,所以不希望执行I/O或锁定操作 >!!一条
(go-loop [state {}]
(let [[value task] (alts! tasks)]
...work...
(recur state))
我觉得我不明白我可以用各种方法来完成这项工作,所以我想在这里尝试探索一下
- 内联或通过调用函数:这会阻止循环继续,直到工作完成。因为它位于go块中,所以不希望执行I/O或锁定操作
- >!!一条消息发送到一个由工作者监控的通道:如果通道已满,这将通过停车阻止环路,直到通道有容量为止。这允许螺纹进行其他工作,并允许背压
- >!!一条消息:如果通道已满,将通过休眠运行go循环的线程来阻塞。这可能是不可取的,因为go线程是一种严格有限的资源
- >!!另一个go块中的消息:除非没有可用的go线程,否则这将几乎立即成功。相反,如果通道已满且消耗缓慢,则可能会在短时间内耗尽系统中的go线程
- >!!带有线程块的消息:与go块类似,但使用系统线程而不是go线程,因此上限可能更高
- 放!一条信息:不清楚权衡是什么
- 将来调用work函数:将工作从clojure代理池中分配给线程执行,允许go循环继续。如果输入速率超过输出速率,则会无限制地增长代理池队列
此摘要正确且全面吗?如果要完成的工作完全受CPU限制,则我可能会在
go
块中内联完成,除非这是一个可能需要很长时间的操作,并且我希望go
块继续响应其他消息
通常,任何不阻塞、睡眠或执行I/O的工作都可以安全地放入go
块中,而不会对系统的吞吐量产生重大影响
您可以使用>代码>将工作提交给工作人员或工作人员池。我几乎不会使用>代码>在go
块中,因为它可以阻止分配给运行go
块的有限数量的线程之一
当您需要执行I/O或可能长时间运行的计算时,请使用线程
而不是go
。这非常类似于future
——它创建了一个真正的线程——但它返回一个类似go
的通道
put
是一个较低级别的操作,通常用于core.async的“边界”,将其连接到传统的基于回调的接口。很少有理由使用put代码>在go
中
async可以支持对线程创建方式的细粒度控制。我在一篇博文中展示了一些可能性