2016-02-26 48 views
4

比方說,我這樣做:未來總是會創建一個新的線程嗎?

(future 
    (do-the-thing)) 

我保證,無論什麼(do-the-thing)呢,

  • 一個全新的線程將被創建,而不是讓一個從池中或類似的東西那?
  • 沒有什麼比(do-the-thing)永遠運行在新的線程?
  • 一旦(do-the-thing)在該新線程上執行,線程將終止?

如果不是,那麼在什麼情況下這些假設是錯誤的?

+0

我的理解是,Clojure的未來不使用專業化圖書館的期貨只不過是Java期貨。所以這可能已經被問及作爲Java問題回答。 –

+0

@ChrisMurphy如果您可以將我鏈接到Java問題,那將非常棒! –

+0

Java期貨板塊,而斯卡拉的沒有。然而,Clojure的這個缺點已經被這個[library]修復了(https://github.com/leonardoborges/imminent)。 –

回答

4

簡短的回答是沒有

從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

Agent.java

volatile public static ExecutorService soloExecutor = Executors.newCachedThreadPool(
    createThreadFactory("clojure-agent-send-off-pool-%d", sendOffThreadPoolCounter)); 

你可以看到,soloExecutorExecutors.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 

所以,你可以確認以前的線程終止運營,創造了新的線程。

+0

爲了以防人們感興趣:'core.async'使用'newFixedThreadPool':http://stackoverflow.com/questions/949355/java-newcachedthreadpool-versus-newfixedthreadpool – ClojureMostly

相關問題