是否应该将 `while true` 放在 clojure core.async 线程中?
Should one put `while true` inside of a clojure core.async thread?
我有这个 producer/consumer 模式,我一直在用 core.async thread
函数制作,如下所示:
(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)))))))))
然而,当我阅读 the documentation 的 thread
时,它说:
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.
听起来它期待线程被称为一次性;并不是说它是为其中的 while
循环而构建的。
我不应该在 thread
块中执行 while true
吗?或者当我关闭 thread
的结果 chan 时线程会被清理吗?
线程肯定不会被清理,所以,是的,您可能不应该使用 while true
循环。您可以使用带退出条件的循环代替它。
常见模式是使您的 go
-例程(简单地说,在其他线程上执行的循环)依赖于您的输入通道。换句话说,当向 go
-routine 提供数据的通道关闭时 - go
-routine 被关闭。
我已经稍微重写了你的代码,可能遗漏了一些东西,但我希望你能明白:
(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))))))
我还用 go
调用替换了 thread
调用。这是 thread
的 "lightweight" 版本,它使用线程停放而不是阻塞本机线程。如果您需要 OS 个线程,您可以将其替换为 (thread (loop ...
。
请看这里的讨论:http://www.braveclojure.com/core-async/
最重要的一句话是:
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-运行 任务正是 Java 线程的用途。由于您有一个长 运行 任务(它出现了吗?)它应该有自己的线程。
JVM 可以处理一千个用户线程 w/o 现代硬件上的问题。
我有这个 producer/consumer 模式,我一直在用 core.async thread
函数制作,如下所示:
(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)))))))))
然而,当我阅读 the documentation 的 thread
时,它说:
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.
听起来它期待线程被称为一次性;并不是说它是为其中的 while
循环而构建的。
我不应该在 thread
块中执行 while true
吗?或者当我关闭 thread
的结果 chan 时线程会被清理吗?
线程肯定不会被清理,所以,是的,您可能不应该使用 while true
循环。您可以使用带退出条件的循环代替它。
常见模式是使您的 go
-例程(简单地说,在其他线程上执行的循环)依赖于您的输入通道。换句话说,当向 go
-routine 提供数据的通道关闭时 - go
-routine 被关闭。
我已经稍微重写了你的代码,可能遗漏了一些东西,但我希望你能明白:
(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))))))
我还用 go
调用替换了 thread
调用。这是 thread
的 "lightweight" 版本,它使用线程停放而不是阻塞本机线程。如果您需要 OS 个线程,您可以将其替换为 (thread (loop ...
。
请看这里的讨论:http://www.braveclojure.com/core-async/
最重要的一句话是:
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-运行 任务正是 Java 线程的用途。由于您有一个长 运行 任务(它出现了吗?)它应该有自己的线程。
JVM 可以处理一千个用户线程 w/o 现代硬件上的问题。