Idiomatic Clojure way to spawn and manage background threads Idiomatic Clojure way to spawn and manage background threads multithreading multithreading

Idiomatic Clojure way to spawn and manage background threads


You don't need a do in your loop; it's implied. Also, while there's nothing wrong with an unconditional loop-recur, you may as well use (while true ...).

future is a fine tool for this; don't let it bother you that you never get a value back. That should really bother you if you use an agent rather than a future, though - agents without values are madness.

However, who said you need to future-cancel? Just make one of the steps in your future be to check whether it's still needed. Then no other parts of your code need to keep track of futures and decide when to cancel them. So something like

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

would be a viable approach.


Using agents for background recurring tasks seems neater to me

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

Now all you have to do is to initiate the loop

(send-off my-agent my-background-task)

The my-backgound-task function is sending itself to the calling agent after its invocation is done.

This is the way how Rich Hickey performs recurring tasks in the ant colony example application: Clojure Concurrency