I need to implement an infinite operation in a Clojure program. I hope the syntax is reasonably clear for Java programmers too:
(defn- my-operation
(future
(while @continue
(do things)
(Thread/sleep polling-time)))
That gives me exactly what I want, the operation in a different thread so it does not block the main one, and also a pretty clear and straightforward syntax without having to deal with native Java functions which would force me to use the dot special form.
But the definition of a Java future is a "representation of the result of an asynchronous computation" and in this case, well, I'm not really doing anything with the result.
This will tie up a thread in the thread pool that Clojure manages, and uses for such things. The intended use of that thread pool is for short running operations, so it's kind-of a misuse. Also, the intention behind a future
is to calculate a value once so it can be dereferenced multiple times, so that's kinds-of a misuse too.
There are lots of other options for long running tasks, including using Java's Executor framework, core-async or starting your own thread.
(defonce background-thread (doto (Thread. (fn []
(while @continue
(do things)
(Thread/sleep polling-time))))
(.setDaemon true)
(.start)))
As others have mentioned, it might be worth thinking about unhandled exceptions. Stuart Sierra's blog post is a great place to start.
The docstring for future
says that it returns something you can call deref
on. It is a reference type in the same way that delay
or atom
is, with it's own semantics of how it get's a value and while it's true you could just create a future and let it run forever, if you see a future in some code, it implies that you care about the value it produces.
(clojure.repl/doc future)
-------------------------
clojure.core/future
([& body])
Macro
Takes a body of expressions and yields a future object that will
invoke the body in another thread, and will cache the result and
return it on all subsequent calls to deref/@. If the computation has
not yet finished, calls to deref/@ will block, unless the variant of
deref with timeout is used. See also - realized?.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With