2016-05-03 8 views
4

Я этот производитель/потребитель модель я уже делал с core.async thread функции следующим образом:Должен ли кто-то поставить `while true` внутри потока core.async clojure?

(defn -db-producer-factory [order-ids-chan next-chan] 
    (thread 
    (while true 
     (do 
     (let [order-id (<!! order-ids-chan)] 
      (condp = order-id 
      :finished (do 
         (>!! next-chan :finished)) 
      (supress-w-nextexc 
       (->> 
       ; get denorm'd order 
       (-> (r/-get-order :live order-id) 
        denorm/order->denormalized) 
       ; put in a map to avoid nils 
       (hash-map :data) 
       (>!! next-chan))))))))) 

Однако, когда я прочитал the documentation для thread, он говорит:

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

Похоже, что ожидаемая нить будет называться единовременно; не то, что он построен для петли while.

Должен ли я не делать while true в thread блоке? Или поток будет очищен, когда я закрою результат chan thread?

ответ

1

Нить не будет очищена точно, поэтому да, вероятно, вы не должны использовать цикл while true. Вместо него вы можете использовать цикл с условием выхода.

Общий шаблон - сделать ваши go -routines (просто говоря, петли, которые выполняются в другом потоке) в зависимости от ваших входных каналов. Другими словами, когда канал, который предоставляет данные для go -routine, закрыт - go -routine выключен.

Я переписан ваш код немного, вероятно, что-то пропустил, но я надеюсь, что вы получите идею:

(defn -db-producer-factory [order-ids-chan next-chan] 
    (go-loop [order-id (<! order-ids-chan)] 
    (condp = order-id 

     nil 
     ;; exiting 
     nil 

     :finished (do 
        (>! next-chan :finished) 
        (recur (<! order-ids-chan))) 
     (do 
     (supress-w-nextexc 
     (->> 
      (-> (r/-get-order :live order-id) 
       denorm/order->denormalized) 
      (hash-map :data) 
      (>! next-chan))) 
     (recur (<! order-ids-chan)))))) 

Также я заменил thread вызов с go вызова. Это «легкая» версия thread, в которой используется парковка нитей вместо блокировки собственной нити. Если вам нужны потоки ОС, вы можете заменить его на (thread (loop ....

+0

У меня есть трудное время, полагая, что 'loop' внутри' thread' сможет быть утилизирован/освобожден/мусор собран, но вы ответили на мой вопрос! – Micah

+0

получил это очищено для меня в clojure # core-async slack room. благодаря! – Micah

0

Пожалуйста, смотрите обсуждение здесь: http://www.braveclojure.com/core-async/

Самое важное предложение:

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

Долгосрочные задачи - это именно то, для чего предназначены потоки Java. Поскольку у вас давняя задача (она появляется?), Она должна иметь собственный поток.

JVM может обрабатывать тысячи пользовательских потоков без проблем на современном оборудовании.

+1

Вопрос не в том, чтобы иметь длинную нить. Речь шла о длительном потоке, который будет работать даже после того, как он больше не понадобится, что может вызвать утечку памяти. –