2024 Clojure 状况调查中分享您的想法!

欢迎!请查阅关于页面以了解更多关于这个网站的信息。

0
Clojure
已重新分类

我正在尝试将一个通道转换为序列。这是我现在正在使用的方式

(defn chan->seq [ch]
  (when [v (<!! ch)]
    (lazy-seq (cons v (chan->seq ch)))))

它工作,但使用了阻塞读取,所以当前的线程将在通道关闭之前被阻塞,并且您不能同时运行许多这个函数的调用。能否有这个函数的非阻塞版本呢?

这个示例展示了这个问题

(doseq [_ (range 20)]
  (go (chan->seq (chan 10))))

(go (println :OK))

最后一个打印不出来,因为 chan->seq 调用正占用线程池中的所有线程。如果将 20 改为 5(在新的 repl 会话中)则可以工作。

1 答案

0

编辑

你的实现是好的。

我们编写(并使用)了一些非常类似的东西

https://github.com/techascent/tech.parallel/blob/cc1b9b0ef8a0893fe1278a700a4dbb0271f92156/src/tech/parallel.clj#L38-L53

你不可能有1000次这个函数同时激活

我不太确定这一点。你尝试过吗?

在这种情况下,可能更为复杂。你可能会需要了解一些关于问题的其他信息(比如通道上出现项目时的模式/时间/频率),然后利用这些信息构建一个非阻塞的、可能可重启并且带有超时的解决方案,或者类似的方法。在许多情况下,JavaScript 仍然是有效的单线程。
...