什么是惯用的Clojure方法来创建一个在后台循环的线程,对某些共享引用进行更新并管理它的生命周期?我发现自己正在使用future
,但感觉有点像黑客,因为我永远不会返回有意义的值。 E.g:
(future (loop [] (do
(Thread/sleep 100)
(dosync (...))
(recur))))
另外,当不再需要后台处理时,我需要小心future-cancel
这个。关于如何在Clojure / Swing应用程序中编排它的任何提示都会很好。例如。添加到我的UI中的虚拟JComponent
可能是一个想法。
答案 0 :(得分:9)
你的循环中不需要do
;这是隐含的。此外,虽然无条件循环复发没有任何问题,但您也可以使用(而真实......)。
future
是一个很好的工具;不要让你觉得你永远不会得到回报。如果你使用代理而不是未来,这应该真的打扰你 - 尽管 - 没有价值观的代理商是疯狂的。
然而,谁说你需要future-cancel
?只需在将来的一个步骤中检查是否仍然需要它。然后,您的代码中没有其他部分需要跟踪期货并决定何时取消它们。像
(future (loop []
(Thread/sleep 100)
(when (dosync
(alter some-value some-function))
(recur)) ; quit if alter returns nil
))
将是一种可行的方法。
答案 1 :(得分:0)
使用代理进行后台重复性任务似乎更适合我
(def my-ref (ref 0))
(def my-agent (agent nil))
(defn my-background-task [x]
(do
(send-off *agent* my-background-task)
(println (str "Before " @my-ref))
(dosync (alter my-ref inc))
(println "After " @my-ref)
(Thread/sleep 1000)))
现在你所要做的就是启动循环
(send-off my-agent my-background-task)
my-backgound-task
函数在调用完成后将自身发送给调用代理。
这就是Rich Hickey在蚁群示例应用程序中执行重复任务的方式:Clojure Concurrency