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次此函数调用

我对这一点不是太确定。您尝试过吗?

在资源受限的一些条件下,暂停线程的栈使用可能会导致内存压力,但总的来说,现代调度器在处理大量暂停线程时表现良好(如果恢复线程不是 O(1),至少在我们使用的情况下——AWS上的各种EC2机器上运行的OpenJDK Linux系统——我会感到惊讶)。

希望这能有所帮助。

by
不需要一定是最少的1000,20个也行。我已在问题中添加了一个例子。
by
啊,如果是那样的话,`go` 就是罪魁祸首。`go` 使用自己的线程池,线程并不多。但是!因为是阻塞读取,所以这里甚至不需要 `go`。看看我链接的实现,它使用了很多线程。
by
如果我想在 `go` 块内使用这个函数怎么办?或者在 Clojurescript 中,Clojurescript 中没有阻塞操作。
by
编辑了 by
在这种情况下,可能有点复杂。你可能需要了解一些关于问题的其他信息(如项目在通道显示的模式/时间/频率),然后使用这些信息设计一种非阻塞的东西,可能是可重启动的,并且有超时,或者类似的东西。在许多情况下,JavaScript仍然是有效单线程的。
...