Multithreading 在core.async中执行块与线程

Multithreading 在core.async中执行块与线程,multithreading,clojure,core.async,Multithreading,Clojure,Core.async,发件人: 为了更具体一点,让我们看看当我们试图发布 某些HTTP GET请求使用core.async。让我们从天真开始 解决方案,通过CLJHTTP使用阻塞IO (defn blocking-get [url] (clj-http.client/get url)) (time (def data (let [c (chan) res (atom [])] ;; fetch em all (doseq [i (range 1

发件人:

为了更具体一点,让我们看看当我们试图发布 某些HTTP GET请求使用core.async。让我们从天真开始 解决方案,通过CLJHTTP使用阻塞IO

(defn blocking-get [url]
  (clj-http.client/get url))


(time
   (def data
     (let [c (chan)
           res (atom [])]
       ;; fetch em all
       (doseq [i (range 10 100)]
         (go (>! c (blocking-get (format "http://fssnip.net/%d" i)))))
       ;; gather results
       (doseq [_ (range 10 100)]
         (swap! res conj (<!! c)))
       @res
       )))
(defn阻塞获取[url]
(clj-http.client/get-url))
(时间
(def数据
(让[c(陈)
res(原子[])]
把他们都拿来
(doseq[i(范围10 100)]
(go(>!c)阻塞获取(格式)http://fssnip.net/%d"我(()()))
收集结果
(doseq[u10(范围100)]
(交换!res conj)(
在这里,我们尝试使用go获取90个代码片段(并行)
阻塞(和阻塞IO)。这花费了很长时间,这是因为
go块线程被长时间运行的IO操作“占用”。
通过将go块切换到正常状态,可以改善这种情况
线程

(time
   (def data-thread
     (let [c (chan)
           res (atom [])]
       ;; fetch em all
       (doseq [i (range 10 100)]
         (thread (>!! c (blocking-get (format "http://fssnip.net/%d" i)))))
       ;; gather results
       (doseq [_ (range 10 100)]
         (swap! res conj (<!! c)))
       @res
       )))
(时间)
(def数据线程
(让[c(陈)
res(原子[])]
把他们都拿来
(doseq[i(范围10 100)]
(线程(>!!c(阻塞获取)(格式)http://fssnip.net/%d"我(()()))
收集结果
(doseq[u10(范围100)]
(交换!res conj)(

“go块线程被长时间运行的IO操作占用”是什么意思?

Go块旨在成为一种轻量级的协作线程;它们通过在池中使用几个线程并在停止时切换Go块(例如,在使用
等待通道时),提供类似线程的行为,开销比完整的JVM线程要少。当您在阻止JVM线程的锁,因此JVM线程很快就会用完。大多数标准Java(和Clojure)IO操作都会在等待时阻止当前线程

“go块线程被长时间运行的IO操作占用”是什么意思

专用于服务go块*的线程数量有限。如果在其中一个线程上执行阻塞I/O操作,则在该操作完成之前,该线程不能用于任何其他目的(除非该线程被中断)。非go块线程也是如此(即,从
thread
函数返回的线程),但非go块线程并不来自有限的go块线程池。因此,如果在go块中执行阻塞i/O,则会“占用”go块的线程,使其不被其他go块使用,即使该线程没有执行任何实际工作(它只是在等待I/O操作)


*这个数字目前正好是JVM可用处理器数量的42+。

I虽然clojure也会使用ForkJoin,但看起来不是。它使用一个简单的FixedThreadpool。这有什么原因吗?Scala ForkJoin甚至可以告诉执行器它正在阻止代码,以便建议生成更多线程。()和()很抱歉,这不是2+个可用处理器吗?不是42+…?go block线程池是每个进程还是每个JVM或每台机器?每个进程和每个JVM之间的区别是什么?链接似乎已失效。这一个有效:(减去尾部斜杠)