考虑一个core.async通道,它是这样创建的:
definer
让我们假设值被放置并从不同的地方被带到这个通道(例如,在循环中)。
如何在特定时间刷新频道上的所有项目?
例如,可以将通道设为原子,然后产生如下事件:
(def c (chan))
还有其他方法可以吗?
答案 0 :(得分:0)
让我们更清楚地定义您似乎想要做的事情:您在几个循环中运行代码,每个循环都将数据放在同一个通道上。你希望能够告诉他们所有人:“你投入价值的渠道已经不再好了;从现在开始,把你的价值放在其他渠道上。”如果这不是你想要做的,那么你原来的问题没有多大意义,因为没有“刷新”要做 - 你要么把价值放在频道上,要么你没有。
首先,了解您的方法不起作用的原因,您的问题的评论会触及:如果您deref
原子c
,您会获得一个频道,并且该值始终是相同的渠道。您的go-loop
中的代码已调用>!
并且当前已停放,等待接收者。当您关闭@c
时,这些停靠的线程会停留(当从某个频道<{1}} 时停靠的任何人都会在频道关闭时立即获得值<!
,但停放的nil
将只停留在停车位。您可以整天>!
reset!
,但停放的主题仍然停留在他们从c
获得的先前值。
那么,你是怎么做到的?这是一种方法。
deref
因此,我们将创建5个工作循环,将其结果放在(require '[clojure.core.async :as a
:refer [>! <! >!! <!! alt! take! go-loop chan close! mult tap]])
(def rand-int-chan (chan))
(def control-chan (chan))
(def control-chan-mult (mult control-chan))
(defn create-worker
[put-chan control-chan worker-num]
(go-loop [put-chan put-chan]
(alt!
[[put-chan (rand-int 10)]]
([_ _] (println (str "Worker" worker-num " generated value."))
(recur put-chan))
control-chan
([new-chan] (recur new-chan)))))
(defn create-workers
[n c cc]
(dotimes [n n]
(let [tap-chan (chan)]
(a/tap cc tap-chan)
(create-worker c tap-chan n))))
(create-workers 5 rand-int-chan control-chan-mult)
上,我们将为它们提供“控制通道”。我会让你自己探索rand-int-chan
和mult
,但简而言之,我们正在创建一个我们可以设置值的单一频道,然后将该值广播到所有点击它的频道。
在我们的工作循环中,我们执行以下两项操作之一:将值放在我们创建它时使用的tap
上,或者我们将取消此控制通道的值。我们可以巧妙地让工作线程知道通过实际处理新通道来改变其值的通道已经改变了,然后它将在下一次通过循环时绑定。所以,要看到它的实际效果:
rand-int-chan
这将从通道中随机获取,并且工作线程将打印它已生成一个值,以确定多个线程确实参与此处。
现在,假设我们想要更改频道以将随机整数置于其上。没问题,我们这样做:
(<!! rand-int-chan)
=> 6
Worker2 generated value.
我们创建了频道,然后我们将该频道放到我们的(def new-rand-int-chan (chan))
(>!! control-chan new-rand-int-chan)
(close! rand-int-chan) ;; for good measure, may not be necessary
上。当我们这样做时,任何工作线程都会执行其control-chan
的第二部分,它只是循环回到alt!
的顶部,除了这次,go-loop
将被绑定我们收到的put-chan
。所以现在:
new-rand-int-chan
这给了我们整数,这正是我们想要的。由于我们关闭了频道,因此从旧频道(<!! new-rand-int-chan)
=> 3
Worker1 generated value.
的所有尝试都会提供<!!
:
nil
答案 1 :(得分:0)
使用into将所有内容读取到矢量中,不要使用它。
(go (async/into [] c))