2013-12-10 56 views
8

我有一个顶级core.async去循环。我希望它无限期地运行,至少直到我用CTRL-C或kill或类似的信号发出信号。我目前使用java.lang.Runtime/addShutdownHook这样的:优雅地退出一个Clojure core.async去死循环

(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"))) 

这里是我的问题:

  1. 如果我启动REPL和(run)然后开始运行,并在后台线程。当我退出REPL时,我看不到所需的关闭消息。

  2. 但是,当我从lein run运行时,go循环立即退出并显示“SHUTDOWN”。

两者都不是我想要的。

我不一定期望找到适用于所有JVM的解决方案。我开发在Mac上并部署到Ubuntu的,所以我想找到两个有效的解决方案:

  • 的Mac JVM:Java版本“1.7.0_45”的Java(TM)SE运行时环境(建1.7.0_45-b18)Java HotSpot™64位服务器虚拟机(版本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,混合模式)

+0

参见:http://stackoverflow.com/questions/11709639/how-to-catch-ctrlc-in-clojure –

+0

参见:http://stackoverflow.com/questions/18612063/clojure- core-async-cpu-timeout-timeout –

回答

4

go函数返回一个通道。您可能想要在关机挂钩中登录(close! chan)

如果您运行的是lein run,则需要一个主函数,它将调用(run)开始执行线程。

(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))) 
+0

当您从(a)REPL运行时,您是否看到关闭消息; (b)通过'lein run'运行? –

+0

如果(a)'lein repl',case(b)'lein run'确实显示关机,没有关机消息 – edbond

+0

如果我用'Ctrl-D'或使用'Ctrl-D'退出时运行'lein trampoline repl'关闭显示, (退出)'功能 – edbond

-1

关于第1部分:“当我退出REPL,我看不到想要的关机信息。“我认为关机线程没有连接到lein repl的控制台。

关于第2部分:go循环启动后,它在后台线程中运行。由于主线程在创建go块后退出,程序关闭。为了使循环寿命长,需要将其置于正常的loop中。 (也可以把Thread/sleep放在里面!)

+1

go blocks不在线程中运行 –