我在Clojure go块中使用Thread / sleep存在内部冲突。通常不建议在go块中使用任何长时间运行的进程,Stuart Sierra mentions that sleeping in go block is not preferred:
一般情况下,任何不会阻塞,休眠或进行I / O的工作都可以安全地放入go块中,而不会对系统的吞吐量产生重大影响。
在我的情况下,我想听一个频道上的消息,并在通知用户之前将它们分组,如果它们来得快。或者,如果只有一条消息出现,请通知用户。在我的特定用例中,几个消息快速连续或单独发送是相当常见的,并且消息不可能定期出现。
为实现这一目标,我有一个等待频道输入的go-loop
块。当它收到它时会睡一会儿(最多一两秒),检查同时是否有任何其他输入到达某个频道,并根据该信息通知用户整件事情或只传递第一条消息。
我的应用程序中不会有一堆这样的go
块,只有一个。由于Clojure总是产生多个线程来为块提供服务,因此在睡眠中阻塞一个线程在实践中不应成为问题。但从理论上讲,我不知道是否有一种更优雅的方法可以处理这个问题,而不会占用这样的线程?
答案 0 :(得分:9)
您应该使用clojure.core.async/timeout
而不是Thread/sleep
中的阻止。 an example on ClojureDocs与您的方案非常相似:
(go-loop [seconds (atom 0)
add-seconds! #(swap! seconds + %)]
(println "Waiting 1 second")
(<! (timeout 1000))
(add-seconds! 1)
(println "Waiting 2 seconds")
(<! (timeout 2000))
(add-seconds! 2)
(println
(format "Waited %s seconds"
@seconds)))