让我说我这样做:
(future
(do-the-thing))
我保证,无论(do-the-thing)
做什么,
(do-the-thing)
之外什么都不会在新线程上运行?(do-the-thing)
在该新线程上执行,该线程将终止?如果没有,在什么情况下这些假设会是假的?
答案 0 :(得分:4)
简短回答是否
来自clojure' core.clj:
(defmacro future
...
[& body] `(future-call (^{:once true} fn* [] ~@body)))
...
(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));
您可以看到soloExecutor
Executors.newCachedThreadPool()
来自document of Executors.newCachedThreadPool:
创建一个根据需要创建新线程的线程池,但在它们可用时将重用以前构造的线程。这些池通常会提高执行许多短期异步任务的程序的性能。如果可用,执行调用将重用先前构造的线程。如果没有可用的现有线程,则将创建一个新线程并将其添加到池中。未使用60秒的线程将终止并从缓存中删除。因此,长时间闲置的池不会消耗任何资源。请注意,可以使用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
因此,您可以确认先前的线程已终止并且已创建新线程。