【问题标题】:Does future always create a new thread?未来是否总是创建一个新线程?
【发布时间】:2016-06-09 01:56:09
【问题描述】:

假设我这样做:

(future
  (do-the-thing))

我是否可以保证,无论 (do-the-thing) 做什么,

  • 将创建一个全新的线程,而不是从池中获取一个或类似的东西?
  • 除了(do-the-thing) 之外的任何东西都不会在该新线程上运行?
  • 一旦(do-the-thing) 在那个新线程上执行,线程会终止吗?

如果不是,在什么情况下这些假设是错误的?

【问题讨论】:

  • 我的理解是,在不使用专用库的情况下,Clojure 中的期货只不过是 Java 期货。所以这可能已经作为一个 Java 问题被问及并得到了回答。
  • @ChrisMurphy 如果您可以将我链接到 Java 问题,那就太好了!
  • Java 期货块,而 Scala 没有。然而,Clojure 中的这个缺点已通过 library 得到修复。
  • @ChrisMurphy 我不明白这与我的问题有什么关系。你能解释一下吗?
  • 我认为@ymonad 已经很好地回答了你的问题。我想补充的一件事是,即使它的实现方式不同,你也不应该依赖它来做任何重要的事情。 AFAIK 这没有任何记录,因此它是一个实现细节,将来总是会改变,并且会破坏任何依赖于特殊行为的代码。如果你真的需要一个线程,那就找一个真正的 Java 线程。

标签: multithreading clojure future


【解决方案1】:

简短的回答是

来自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

创建一个线程池,根据需要创建新线程,但在可用时将重用以前构造的线程。这些池通常会提高执行许多短期异步任务的程序的性能。如果可用,对执行的调用将重用以前构造的线程。如果没有可用的现有线程,将创建一个新线程并将其添加到池中。六十秒内未使用的线程将被终止并从缓存中删除。因此,保持空闲足够长时间的池不会消耗任何资源。请注意,可以使用 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

因此您可以确认之前的线程已终止并创建了新线程。

【讨论】:

猜你喜欢
  • 2014-01-27
  • 2010-10-10
  • 2012-03-13
  • 1970-01-01
  • 1970-01-01
  • 2012-11-14
  • 2019-08-16
  • 2015-07-26
  • 1970-01-01
相关资源
最近更新 更多