我正在阅读Fogus关于Clojure Joy的书,在并行编程章节中,我看到了一个函数定义,它肯定想要说明一些重要但我无法找到的东西.而且,我看不出这个函数是什么 - 当我执行时,它什么也没做:
(import '(java.util.concurrent Executors))
(def *pool* (Executors/newFixedThreadPool
(+ 2 (.availableProcessors (Runtime/getRuntime)))))
(defn dothreads! [f & {thread-count :threads
exec-count :times
:or {thread-count 1 exec-count 1}}]
(dotimes [t thread-count]
(.submit *pool* #(dotimes [_ exec-count] (f)))))
Run Code Online (Sandbox Code Playgroud)
我试图以这种方式运行:
(defn wait [] (Thread/sleep 1000))
(dothreads! wait :thread-count 10 :exec-count 10)
(dothreads! wait)
(dothreads! #(println "running"))
Run Code Online (Sandbox Code Playgroud)
......但它返回零.为什么?
所以,这里是相同的代码,稍微调整一下,以便传递的函数传递dothreads!内部的计数dotimes.
(import 'java.util.concurrent.Executors)
(def ^:dynamic *pool* (Executors/newFixedThreadPool (+ 2 (.availableProcessors (Runtime/getRuntime)))))
(defn dothreads! [f & {thread-count :threads
exec-count :times
:or {thread-count 1 exec-count 1}}]
(dotimes [t thread-count]
(.submit *pool* #(dotimes [c exec-count] (f c)))))
(defn hello [name]
(println "Hello " name))
Run Code Online (Sandbox Code Playgroud)
尝试像这样运行:
(dothreads! hello :threads 2 :times 4)
Run Code Online (Sandbox Code Playgroud)
对我来说,它会打印一些效果:
Hello 0
Hello 1
Hello 2
Hello 3
nil
user=> Hello 0
Hello 1
Hello 2
Hello 3
Run Code Online (Sandbox Code Playgroud)
所以,请注意你在调用函数时犯的一个错误:你传入:thread-count和:exec-count作为键,而那些实际上是在内部发生的解构中的绑定dothreads!.关键字是以冒号开头的单词,:threads和:times.
至于这段代码实际上做了什么:
它创建了一个新的固定大小的线程池,它最多可以使用
机器中的核心数+ 2.调用此池*pool*并使用Java Executor Framework创建.有关详细信息,请参见[1].
该dothreads!函数获取一个将exec-count在每个thread-count线程上调用次数的函数.因此,在上面的示例中,您可以清楚地看到每个线程被调用4次(:threads为2且:times为4).
此函数返回nil的原因是函数dothreads!不返回任何内容.submit线程池的方法在Java中返回void,这意味着它在Clojure中返回nil.如果你要在函数的末尾添加一些其他表达式:
(defn dothreads! [f & {thread-count :threads
exec-count :times
:or {thread-count 1 exec-count 1}}]
(dotimes [t thread-count]
(.submit *pool* #(dotimes [c exec-count] (f c))))
(* thread-count exec-count))
Run Code Online (Sandbox Code Playgroud)对于上面的示例,它将返回8(2*4).只返回函数中的最后一个表达式,因此如果在函数中写入,(fn [x y] (+ x y) (* x y))则始终返回产品.总和将被评估,但它将是无用的.所以,不要这样做!如果你想为一个函数添加更多的那个表达式,请确保除了最后一个表达式之外的所有表达式都有副作用,否则它们将无用.
#(dotimes [c exec-count] (f c))和[1] http://download.oracle.com/javase/tutorial/essential/concurrency/executors.html
| 归档时间: |
|
| 查看次数: |
700 次 |
| 最近记录: |