16

什么是惯用的 Clojure 方法来创建一个在后台循环的线程,对某些共享引用进行更新并管理其生命周期?我发现自己正在future为此使用,但感觉有点像黑客,因为我从不返回有意义的值。例如:

(future (loop [] (do
    (Thread/sleep 100)
    (dosync (...))
    (recur))))

future-cancel另外,当不再需要后台处理时,我需要注意这一点。关于如何在 Clojure/Swing 应用程序中编排它的任何提示都会很好。JComponent例如,添加到我的 UI 中负责在窗口关闭时终止线程的虚拟对象可能是一个想法。

4

2 回答 2

9

你不需要 ado在你的循环中;这是暗示的。此外,虽然无条件循环递归没有任何问题,但您也可以使用 (while true ...)。

future是一个很好的工具;不要让您永远不会获得价值而困扰您。但是,如果您使用代理而不是未来,那真的会打扰您 - 没有价值观的代理是疯狂的。

但是,谁说你需要future-cancel?只需让您未来的步骤之一是检查它是否仍然需要。然后,您的代码的任何其他部分都不需要跟踪期货并决定何时取消它们。所以像

(future (loop []
          (Thread/sleep 100)
          (when (dosync
                 (alter some-value some-function))
            (recur)) ; quit if alter returns nil
          ))

将是一种可行的方法。

于 2011-03-13T19:34:35.533 回答
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

于 2011-03-13T21:06:46.143 回答