【发布时间】:2011-06-01 10:17:17
【问题描述】:
如何在 Clojure 中创建一个持续运行的后台进程?使用“未来”的循环永远不会以正确的方式结束吗?
【问题讨论】:
标签: concurrency clojure
如何在 Clojure 中创建一个持续运行的后台进程?使用“未来”的循环永远不会以正确的方式结束吗?
【问题讨论】:
标签: concurrency clojure
你可以用一个永远运行的函数来启动一个线程。
(defn forever []
;; do stuff in a loop forever
)
(.start (Thread. forever))
如果您不希望后台线程阻止进程退出,请确保将其设为守护线程:
(doto
(Thread. forever)
(.setDaemon true)
(.start))
如果您想要更多技巧,可以使用 java.util.concurrent.Executors 工厂来创建 ExecutorService。这使得创建线程池、使用自定义线程工厂、自定义传入队列等变得容易。
claypoole lib 将一些工作执行的东西包装成一个对 clojure 更友好的 api,如果那是你想要的。
【讨论】:
我的简单高阶无限循环函数(使用期货):
(def counter (atom 1))
(defn infinite-loop [function]
(function)
(future (infinite-loop function))
nil)
;; note the nil above is necessary to avoid overflowing the stack with futures...
(infinite-loop
#(do
(Thread/sleep 1000)
(swap! counter inc)))
;; wait half a minute....
@counter
=> 31
我强烈建议使用原子或 Clojures 其他引用类型之一来存储结果(如上例中的计数器)。
通过一些调整,您还可以使用这种方法以线程安全的方式启动/停止/暂停进程(例如,测试一个标志以查看是否应该在循环的每次迭代中执行(函数))。
【讨论】:
(defn infinite [f seconds] (future (loop [] (f) (Thread/sleep (* seconds 1000)) (recur))))
infinite-loop 的递归调用在未来内部这一事实意味着它不会在原始函数的堆栈框架内重复。
也许,或者也许是 Lein-daemon? https://github.com/arohner/lein-daemon
【讨论】: