2016-02-26 42 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

相关问题