2015-01-06 4 views
1

Чтение через Core Async walkthrough Не думаю, что я видел этот прецедент. У меня есть один производитель и много одинаковых потребителей.Может ли канал иметь несколько потребителей?

(def mychan (chan)) 
(defn my-expensive-fn [arg] (prn-expensively arg)) 

; four identical consumers 
(go (while true (my-expensive-fn (<!! mychan)))) 
(go (while true (my-expensive-fn (<!! mychan)))) 
(go (while true (my-expensive-fn (<!! mychan)))) 
(go (while true (my-expensive-fn (<!! mychan)))) 

; something generating lots of items 
(doseq [item in lots-of-items] 
    (something-expensive) 
    (>!! mychan item)) 
  1. Правомерно?
  2. Есть ли более идиоматический способ сделать это, а не повторять (копировать или в цикле) код потребительского вызова?

ответ

2

Имеет право на чтение с канала из любого места, которое вам нравится. Каждое сообщение будет прочитано не более чем одним из них.

Вместо того, чтобы копировать код, вы можете создавать одинаковые блоки в цикле.

(dotimes [_ 4] 
    (go 
    (while true 
     (my-expensive-fn (<!! mychan))))) 

один вопрос, вы увидите здесь является то, что петля не имеет условия, которое остановит рекурсию, и это имеет смысл, по крайней мере, остановить, если канал закрывается.

(dotimes [_ 4] 
    (go-loop [job (<!! mychan)] 
    (when (some? job) 
     (my-expensive-fn job) 
     (recur (<!! mychan))))) 

Замкнутый канал мгновенно возвращает ноль, и эта версия остановится, когда он получает ноль, а не собираюсь в тугую петлю неоднократно потребляющей и диспетчеризации на ноле.

+0

Блестящий, спасибо большое. – Joe

+0

Рассмотрите возможность использования 'go-loop' вместо' go' + 'loop'. –

+0

обновлено, спасибо – noisesmith

Смежные вопросы