【发布时间】:2018-04-01 14:57:14
【问题描述】:
我使用一些 Java 库来发出非异步获取和发布请求。我曾经将此类请求包装到期货中,它为我解决了“等待问题”(我的意思是等待响应)
(defn unchangeable-lib-request [n]
(Thread/sleep 1000)
n)
(defn process [n]
(let [res (atom [])]
(dotimes [i n]
(future (swap! res conj (unchangeable-lib-request i))))
(loop []
(if (> n (count @res))
(recur)
@res))))
(time (process 9))
;; "Elapsed time: 1000.639079 msecs"
;; => [8 7 5 6 4 3 2 1 0]
但是我需要创建数百个请求,这会产生性能问题。我发现了 core.async 和 go 块。但是如果我将 go-blocks 与这个库一起使用,它不会解决“等待问题”
(defn unchangeable-lib-request [n]
(Thread/sleep 1000)
n)
(defn process [n]
(let [c (async/chan 10)]
(dotimes [i n]
(async/go
(async/>! c (unchangeable-lib-request i))))
(loop [result []]
(if (> n (count result))
(recur (conj result (async/<!! c)))
result))))
(time (process 9))
;; "Elapsed time: 2001.770183 msecs"
;; => [0 4 1 6 7 2 5 3 8]
Go 块只能同时处理 8 个请求。是否有可能编写一些异步包装器来停放 go-block 并提供异步发出 100 个请求而不会相互阻塞的能力?
(defn process [n]
(let [c (async/chan 10)]
(dotimes [i n]
(async/go
(async/>! c (magic-async-parking-wrapper
(unchangeable-lib-request i))))
(loop [result []]
(if (> n (count result))
(recur (conj result (async/<!! c)))
result))))
(time (process 9))
;; "Elapsed time: 1003.2563 msecs"
我知道异步/线程,但这似乎与(未来...)相同。
有可能吗?
【问题讨论】:
-
你读过this吗?
-
你指的是什么?我在那里没有发现任何有用的东西。你的意思是使用 (Thread/sleep _) 不是一个好主意?所以,这就是重点。我已经有一个阻塞操作并且无法更改它。我需要用它做点什么
标签: multithreading concurrency clojure core.async