Предотвратить завершение программы, пока блоки 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
блоки, чтобы закончить свой бизнес.