是否应该将 `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 documentationthread 时,它说:

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 现代硬件上的问题。