Clojure中的线程/睡眠块

时间:2016-11-09 10:42:56

标签: multithreading clojure core.async

我在Clojure go块中使用Thread / sleep存在内部冲突。通常不建议在go块中使用任何长时间运行的进程,Stuart Sierra mentions that sleeping in go block is not preferred

  

一般情况下,任何不会阻塞,休眠或进行I / O的工作都可以安全地放入go块中,而不会对系统的吞吐量产生重大影响。

在我的情况下,我想听一个频道上的消息,并在通知用户之前将它们分组,如果它们来得快。或者,如果只有一条消息出现,请通知用户。在我的特定用例中,几个消息快速连续或单独发送是相当常见的,并且消息不可能定期出现。

为实现这一目标,我有一个等待频道输入的go-loop块。当它收到它时会睡一会儿(最多一两秒),检查同时是否有任何其他输入到达某个频道,并根据该信息通知用户整件事情或只传递第一条消息。

我的应用程序中不会有一堆这样的go块,只有一个。由于Clojure总是产生多个线程来为块提供服务,因此在睡眠中阻塞一个线程在实践中不应成为问题。但从理论上讲,我不知道是否有一种更优雅的方法可以处理这个问题,而不会占用这样的线程?

1 个答案:

答案 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)))