Reputation: 10395
I have this producer/consumer pattern i've been making with core.async thread
functions like so:
(defn -db-producer-factory [order-ids-chan next-chan]
(thread
(while true
(do
(let [order-id (<!! order-ids-chan)]
(condp = order-id
:finished (do
(>!! next-chan :finished))
(supress-w-nextexc
(->>
; get denorm'd order
(-> (r/-get-order :live order-id)
denorm/order->denormalized)
; put in a map to avoid nils
(hash-map :data)
(>!! next-chan)))))))))
However when i read the documentation for thread
, it says:
Executes the body in another thread, returning immediately to the calling thread. Returns a channel which will receive the result of the body when completed.
It sounds like its expecting thread to be called one-off; not that its built for a while
loop within it.
Should i not do while true
in a thread
block? Or will the thread be cleaned up when i close the thread
's result chan?
Upvotes: 4
Views: 878
Reputation: 29958
Please see the discussion here: http://www.braveclojure.com/core-async/
The most important sentence is:
The reason you should use thread instead of a go block when you’re performing a long-running task is so you don’t clog your thread pool.
Long-running tasks are exactly what Java threads are made for. Since you have a long-running task (it appears?) it should have it's own thread.
The JVM can handle a thousand user threads w/o problem on modern hardware.
Upvotes: 0
Reputation: 4513
The thread won't be cleaned up for sure, so, yes, probably you shouldn't use while true
loop. Instead of it you may use loop with exit condition.
Common pattern is to make your go
-routines (simply saying, loops that are executed on other thread) dependent on your input channels. In other words, when channel that provides data to go
-routine is closed - go
-routine is shut down.
I've rewritten your code a little bit, probably missed something, but I hope you'll get the idea:
(defn -db-producer-factory [order-ids-chan next-chan]
(go-loop [order-id (<! order-ids-chan)]
(condp = order-id
nil
;; exiting
nil
:finished (do
(>! next-chan :finished)
(recur (<! order-ids-chan)))
(do
(supress-w-nextexc
(->>
(-> (r/-get-order :live order-id)
denorm/order->denormalized)
(hash-map :data)
(>! next-chan)))
(recur (<! order-ids-chan))))))
Also I've replaced thread
call with go
call. This is "lightweight" version of thread
, that uses thread parking instead of blocking native thread. If you need OS threads, you may replace it with (thread (loop ...
.
Upvotes: 1