Предотвратить завершение программы, пока блоки go выполняются бесконечно?

Я написал отдельный uberjar с методом main, который раскручивает два блока go следующим образом:

(defn -main [& args]
  (let [c (chan)]
    (go (while true
           (>! c (rand))))
    (go (while true
           (<! c)))))

Но когда я запускаю программу, она быстро завершается. Зачем? Мое намерение состоит в том, чтобы блоки go выполнялись бесконечно. Я застрял

 (<!! (chan))

в конце основной функции, чтобы предотвратить завершение. Есть ли лучший способ сделать это?

1 ответ

Решение

Программа завершается, потому что после тех go блоки созданы, основная функция завершена. Ничего не делать, он выходит; это не должно быть большой неожиданностью. Конечно, мы бы предпочли, чтобы основное приложение продолжало работать, пока все go блоки еще живы.

Каждый из тех go блоки производит канал; Вы можете подождать, пока один из них что-то не вернет (хотя в таком виде они никогда не будут). Попробуйте заблокировать с alts!! пока они крутятся

(defn -main
  [& args]
  (let [c (chan)]
    (alts!!
      [(go (while true
             (>! c (rand))))
       (go (while true
             (<! c)))])))

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

(defn -main
  [& args]
  (let [c (chan)]
    (alts!!
      [(go (while true
             (>! c (rand))))
       (go-loop [value (<! c)]
                (if (> value 0.8)
                  value ; return value from the go block
                  (recur (<! c))))])))

Или, сойти с ума, тайм-аут через секунду:

(defn -main
  [& args]
  (let [c (chan)]
    (alts!!
      [(go (while true
             (>! c (rand))))
       (go (while true
             (<! c)))
       (timeout 1000)])))

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

Другие вопросы по тегам