所以,在这里是相同的代码,以便传递给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))
尝试运行它像这样:
(dothreads! hello :threads 2 :times 4)
对于我来说,它打印东西的效果:
Hello 0
Hello 1
Hello 2
Hello 3
nil
user=> Hello 0
Hello 1
Hello 2
Hello 3
所以,注意你调用函数时犯了一个错误:您在通过:线程数和:EXEC数作为关键字,而这些其实都是在T绑定他解构了dothreads!
内部发生的事情。关键字是开始以一个冒号,:threads
和:times
的话。
至于这是什么代码实际上做:
它创建最多将使用你的机器+ 2的 芯数的新的固定大小的线程池。该池称为*pool*
并使用的Java执行器框架创建。有关更多详细信息,请参见[1]。
的dothreads!
函数获取将要在每个thread-count
线程称为exec-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))
它将返回8上面的例子(2 * 4)。只有函数中的最后一个表达式被返回,所以如果在函数中你要写(fn [x y] (+ x y) (* x y))
这将始终返回该产品。总和将被评估,但它将为没有任何。所以,不要这样做!如果你想添加一个表达式到一个函数,确保除了最后一个都有副作用,否则它们就没用了。
- 你也可能注意到了,在其中打印东西的顺序是异步的。所以,在我的机器上,它会打4声,然后返回函数的结果,然后再打4声。线程之间执行函数的顺序是不确定的,但是每个线程中的hello都是顺序的(在Hello 2之前永远不会有Hello 3)。究其原因,顺序性是实际提交给线程池的功能是
#(dotimes [c exec-count] (f c))
和
[1] http://download.oracle.com/javase/tutorial/essential/concurrency/executors.html
谢谢您的详细解释!其实,我对你的代码有一点点玩法。第一次,它没有在cljr中输出任何东西:[link](http://i44.tinypic.com/11io8pl.png) 但是 - 足够奇怪 - 如果我从命令提示符运行cljr(cmd )在Windows上,它将消息打印到cmd窗口! 之后,我尝试了一个匿名函数: (dothreads!#(println“Hello”name):threads 2:times 4) ...但它没有工作,这也很奇怪。 – asdfghjkl
我想也许在“cljr-without-cmd”模式下缺少打印输出的原因是println函数被编译成一些Java(?)中的“System.out.println”调用,它想要打印正确到一些控制台输出(?)。默认情况下,cljr以某种方式在评估源代码时“捕获”这些println,但是当另一个Java线程执行打印时,这些线程不知道在哪里写输出......但这是猜测。 – asdfghjkl
现在完全猜测 - 但也许尝试使用Clojure 1.3运行代码?这就是我测试它的原因。我不知道为什么它没有在你的例子中打印任何东西。 错误,如果你接受我的答案,也请勾选它;) –