应该排空clojure.core.async频道以释放停放的看跌期权

时间:2017-08-03 16:28:05

标签: clojure channel core.async

问题:我有消费者读取的频道,并且在获得足够的数据时可能会停止阅读。当阅读器停止时,它会用clojure.core.async / close关闭通道!

文档说,此时调用关闭后所有对通道的置位应该返回false并且什么都不做。但文档也说明了

  

在所有投放已经交付之后发生逻辑关闭。因此,任何被阻止或停放的看跌期权将被阻止/停放,直到接受者释放它们为止。

这是否意味着在关闭频道的时候释放已经被停放在停放投注中的生产商我应该总是在消费者方面消耗渠道(阅读所有剩余的项目)?以下代码显示go块永远不会完成:

(require '[clojure.core.async :as a])
(let [c (a/chan)]
  (a/go
    (prn "Go")
    (prn "Put" (a/>! c 333)))
  (Thread/sleep 300) ;; Let go block to be scheduled
  (a/close! c))

如果这是真的,我不想阅读所有事件,那么我应该实施例如生产者方面的超时检测不再需要更多数据?

消费者是否有更简单的方式告诉他们#34;足够的"为了回头让生产者也优雅地停下来?

我发现clojure.core.async/put!没有阻止并允许避免不必要的阻止。是否有使用它而不是clojure.core.aasync/>!的缺点?

2 个答案:

答案 0 :(得分:2)

关闭chans释放所有正在阅读它们的人,并且让作家被阻止

这是阅读案例(它运作良好):

user> (def a-chan (async/chan))
#'user/a-chan
user> (future (async/<!! a-chan)
              (println "continuting after take"))
#future[{:status :pending, :val nil} 0x5fb5a025]
user> (async/close! a-chan)
nil
user> continuting after take

以下是对写作案例的测试,正如你所说的那样,耗尽它可能是一个好主意:

user> (def b-chan (async/chan))
#'user/b-chan
user> (future (try (async/>!! b-chan 4)
                   (println "continuting after put")
                   (catch Exception e
                     (println "got exception" e))
                   (finally
                     (println "finished in finally"))))
#future[{:status :pending, :val nil} 0x17be0f7b]
user> (async/close! b-chan)
nil

我没有找到任何证据证明当陈被关闭时卡住的作家解锁了

答案 1 :(得分:1)

此行为是有意的,因为它们在文档中明确说明了它!

在您的情况下,在关闭通道(while (async/poll! c))后执行c以释放所有阻止/停放(消息发送)线程/阻塞。

如果您想对可以执行的操作执行任何操作:

(->> (repeatedly #(async/poll! c))
     (take-while identity))