在core.async中阻止vs线程

qed*_*qed 8 multithreading clojure core.async

来自http://martintrojer.github.io/clojure/2013/07/07/coreasync-and-blocking-io/:

为了更具体一点,让我们看看当我们尝试使用core.async发出一些HTTP GET请求时会发生什么.让我们从天真的解决方案开始,通过clj-http使用阻塞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
       )))
Run Code Online (Sandbox Code Playgroud)

在这里,我们尝试使用go块(并阻塞IO)获取90个代码片段(并行).这需要很长时间,这是因为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
       )))
Run Code Online (Sandbox Code Playgroud)

"长时间运行的IO操作会阻塞块线程"是什么意思?

Joo*_*aat 6

Go块旨在成为一种轻量级的协作线程; 它们提供类似线程的行为,比完整JVM线程更少开销,方法是使用池中的几个线程并在停放时切换块- 例如,在使用时等待通道时<!.当您在阻塞JVM线程的块中调用方法时,线程切换不起作用,因此您很快就会耗尽JVM线程.大多数标准Java(和Clojure)IO操作将在等待时阻止当前线程.