gpt4 book ai didi

Clojure 线程!功能

转载 作者:行者123 更新时间:2023-12-04 22:50:13 27 4
gpt4 key购买 nike

我正在阅读 Fogus 的关于 Clojure 的喜悦的书,在并行编程章节中,我看到了一个函数定义,它肯定想说明一些重要的事情,但我不知道是什么。此外,我看不到这个函数有什么用 - 当我执行时,它什么也不做:

(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)))))

我试图以这种方式运行:
(defn wait [] (Thread/sleep 1000))
(dothreads! wait :thread-count 10 :exec-count 10)
(dothreads! wait)
(dothreads! #(println "running"))

...但它返回零。为什么?

最佳答案

所以,这里是相同的代码,稍作调整,使函数传递给 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

因此,请注意您在调用函数时犯的一个错误:您传入 :thread-count 和 :exec-count 作为键,而这些实际上是在 dothreads! 内部发生的解构中的绑定(bind)。 .关键字是以冒号开头的词, :threads:times .

至于这段代码实际上做了什么:
  • 它创建一个新的固定大小的线程池,最多使用
    您机器中的内核数 + 2 .此池称为 *pool*并且是使用 Java Executor Framework 创建的。有关详细信息,请参阅 [1]。
  • dothreads! function 得到一个将被调用的函数 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))

  • 对于上面的示例,它将返回 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

    关于Clojure 线程!功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8052039/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com