Dav*_* J. 10 java signals clojure core.async
我有一个顶级的core.async go循环.我希望它无限期地运行,至少直到我用CTRL-C或杀死或类似信号来阻止它.我目前正在使用java.lang.Runtime/addShutdownHook,如下所示:
(ns async-demo.core
(:require [clojure.core.async :as async
:refer [<! >! <!! timeout chan alt! go]]))
(defn run [] (go (loop [] (recur))))
(.addShutdownHook (Runtime/getRuntime) (Thread. #(println "SHUTDOWN")))
Run Code Online (Sandbox Code Playgroud)
这是我的问题:
如果我启动REPL (run)然后它启动并在后台线程中运行.当我退出REPL时,我看不到所需的关机消息.
但是,当我运行时lein run,go循环立即退出并显示"SHUTDOWN".
这也不是我想要的.
我不一定希望找到适用于所有JVM的解决方案.我在Mac上开发并部署到Ubuntu,所以我想找到适合两者的解决方案:
Mac JVM:java版"1.7.0_45"Java(TM)SE运行时环境(版本1.7.0_45-b18)Java HotSpot(TM)64位服务器VM(版本24.45-b08,混合模式)
Ubuntu JVM:java版"1.7.0_25"OpenJDK运行时环境(IcedTea 2.3.10)(7u25-2.3.10-1ubuntu0.12.04.2)OpenJDK 64位服务器VM(版本23.7-b01,混合模式)
小智 13
您可以使用信号exit-ch并执行条件来查看是否应该退出循环。通道 + 条件在 clojure 中由alt更好地处理!:
(ns async-demo.core
(:require [clojure.core.async :refer [chan go-loop alt! timeout put!]]))
(defn run
[]
(let [exit-ch (chan)]
(go-loop []
(alt!
(timeout 10) (recur)
exit-ch nil
exit-ch
(let [exit-ch (run)]
(.addShutdownHook (Runtime/getRuntime) (put! exit-ch true)))
Run Code Online (Sandbox Code Playgroud)
如果你只是close!通道,它不会停止循环运行。此外,不需要启动 go 块只是为了将值发送到 channel。
edb*_*ond -2
go函数返回一个通道。您可能想要(close! chan)关闭钩子。
如果你运行,lein run你需要一个 main 函数来调用(run)来启动 go 线程。
(ns async-demo.core
(:require [clojure.core.async :as async
:refer [<! >! <!! timeout chan alt! go close!]]))
(def ch (atom nil))
(defn run []
(go (while true
(<! (timeout 500))
(prn "inside go"))))
(defn -main [& args]
(println "Starting")
(reset! ch (run))
(.addShutdownHook (Runtime/getRuntime)
(Thread. #(do
(println "SHUTDOWN")
(close! @ch))))
(while true
(<!! @ch)))
Run Code Online (Sandbox Code Playgroud)