比方說,我這樣做:未來總是會創建一個新的線程嗎?
(future
(do-the-thing))
我保證,無論什麼(do-the-thing)
呢,
- 一個全新的線程將被創建,而不是讓一個從池中或類似的東西那?
- 沒有什麼比
(do-the-thing)
永遠運行在新的線程? - 一旦
(do-the-thing)
在該新線程上執行,線程將終止?
如果不是,那麼在什麼情況下這些假設是錯誤的?
比方說,我這樣做:未來總是會創建一個新的線程嗎?
(future
(do-the-thing))
我保證,無論什麼(do-the-thing)
呢,
(do-the-thing)
永遠運行在新的線程?(do-the-thing)
在該新線程上執行,線程將終止?如果不是,那麼在什麼情況下這些假設是錯誤的?
簡短的回答是沒有
從Clojure的core.clj:
(defmacro future
...
[& body] `(future-call (^{:once true} fn* [] [email protected])))
...
(defn future-call
...
[f]
(let [f (binding-conveyor-fn f)
fut (.submit clojure.lang.Agent/soloExecutor ^Callable f)]
...
所以未來的執行者是clojure.lang.Agent/soloExecutor
。
volatile public static ExecutorService soloExecutor = Executors.newCachedThreadPool(
createThreadFactory("clojure-agent-send-off-pool-%d", sendOffThreadPoolCounter));
你可以看到,soloExecutor
由Executors.newCachedThreadPool()
創建從document of Executors.newCachedThreadPool:
創建一個可根據需要創建新線程的線程池,但會重用先前構建的線程在可用時。這些池通常會提高執行許多短暫異步任務的程序的性能。調用執行將重用以前構造的線程(如果可用)。如果沒有現有線程可用,則會創建一個新線程並將其添加到池中。未使用六十秒的線程將被終止並從緩存中移除。因此,保持閒置時間足夠長的池不會消耗任何資源。請注意,使用ThreadPoolExecutor構造函數可以創建具有類似屬性但具有不同細節的池(例如,超時參數)。
所以答案是(do-the-thing)
的一些其他工作可以在同一個線程中執行,如果沒有更多的工作,線程將在60秒後終止。
您可以確認的Executors.newCachedThreadPool
行爲在下面的代碼:
(doseq [i (for [x (range 10)] (future (Thread/sleep 1000) (.getId (Thread/currentThread))))] (print @i) (print " "))
執行Clojure中的控制檯這段代碼,你會得到:
50 49 48 47 46 45 44 43 42 41 nil
首次。並且在5秒後再次執行它,您將獲得:
50 49 43 41 45 42 46 47 48 44 nil
因此您可以確認線程是否被重用。
如果執行相同的代碼60秒後,您將獲得:
60 59 58 57 56 55 54 53 52 51 nil
所以,你可以確認以前的線程終止運營,創造了新的線程。
爲了以防人們感興趣:'core.async'使用'newFixedThreadPool':http://stackoverflow.com/questions/949355/java-newcachedthreadpool-versus-newfixedthreadpool – ClojureMostly
我的理解是,Clojure的未來不使用專業化圖書館的期貨只不過是Java期貨。所以這可能已經被問及作爲Java問題回答。 –
@ChrisMurphy如果您可以將我鏈接到Java問題,那將非常棒! –
Java期貨板塊,而斯卡拉的沒有。然而,Clojure的這個缺點已經被這個[library]修復了(https://github.com/leonardoborges/imminent)。 –