我有很多工人正在跑步,把工作项目排除在队列之外。类似的东西:
(def num-workers 100)
(def num-tied-up (atom 0))
(def num-started (atom 0))
(def input-queue (chan (dropping-buffer 200))
(dotimes [x num-workers]
(go
(swap num-started inc)
(loop []
(let [item (<! input-queue)]
(swap! num-tied-up inc)
(try
(process-f worker-id item)
(catch Exception e _))
(swap! num-tied-up dec))
(recur)))
(swap! num-started dec))))
希望num-tied-up
代表在特定时间点执行工作的工人数量。 num-tied-up
的值围绕相当一致的50
,有时60
。由于num-workers
为100且num-started
的值为100(即所有go
例程正在运行),这感觉就像有一个舒适的边距。
我的问题是input-queue
正在增长。我希望它能够徘徊在零标记附近,因为有足够的工人可以从中取出物品。但在实践中,最终它会最大化并丢弃事件。
tied-up
看起来num-workers
有足够的空间,所以工作人员可以从队列中取出工作。
我的问题:
答案 0 :(得分:0)
当我修复代码的缩进时,这就是我所看到的:
(def num-workers 100)
(def num-tied-up (atom 0))
(def num-started (atom 0))
(def input-queue (chan (dropping-buffer 200))
(dotimes [x num-workers]
(go
(swap num-started inc)
(loop []
(let [item (<! input-queue)]
(swap! num-tied-up inc)
(try
(process-f worker-id item)
(catch Exception e _))
(swap! num-tied-up dec))
(recur)))
(swap! num-started dec))
)) ;; These parens don't balance.
忽略额外的parens,我假设是一些复制/粘贴错误,这里有一些观察:
num-started
,但在创建该线程后立即将其减少到go线程之外。在递增之前,减量总是很有可能发生。请记住,产生一个go线程并不意味着当前线程(执行dotimes
执行的产生的线程)将阻止。我可能会弄错,但看起来你的代码假设(swap! num-started dec)
只会在紧接在它上面生成的go线程完成时运行。但事实并非如此,即使你的线程 最终完成了(如上所述,他们也没有)。
答案 1 :(得分:0)
go例程完成的工作不应该执行任何IO或阻塞操作(如线程/休眠),因为所有go例程共享相同的线程池,现在它具有固定大小cpus * 2 + 42。对于IO有界工作,请使用core.async/thread。
请注意,线程池限制了将同时执行的go例程的数量,但是您可以有足够的等待执行。
作为类比,如果您启动Chrome,Vim和iTunes(相当于3个例行程序),但您的笔记本电脑中只有一个CPU(相当于1个大小为1的线程池),那么其中只有一个将执行在CPU中,另一个将等待执行。操作系统是负责暂停/恢复程序的操作系统,因此看起来它们都在同时运行。 Core.async也是这样做的,但不同的是,core.async可以在它们命中时暂停go-routines。
现在回答你的问题:
希望它有所帮助。