multithreading - Clojure 使用零个或一个输入的函数运行多个线程
问题描述
我正在 Clojure 中尝试运行独立线程,但我得到了我不理解的不同行为。
对于我的代码编辑器,我使用的是 Atom(不是 emacs),REPL 是 Chlorine。
我正在测试一个非常简单的函数,它只打印数字。这个从 100 打印到 1 并且不接受任何输入:
(defn pl100 []
"pl100 = Print Loop from 100 to 1"
(loop [counter 100]
(when (pos? counter)
(do
(Thread/sleep 100)
(println (str "counter: " counter))
(recur (dec counter))))))
这个做完全相同的事情,除了它需要一个输入:
(defn pl-n [n]
"pl-n = Print Loop from n to 1"
(loop [counter n]
(when (pos? counter)
(do
(Thread/sleep 100)
(println (str "counter: " counter))
(recur (dec counter))))))
当我使用
(.start (Thread. #(.run pl100)))
; --> prints to console REPL
; --> runs with no errors
这段代码
- 打印到控制台 REPL(我称之为 lein)和
- 运行没有错误
当我使用
(.start (Thread. #(.run (pl-n 100))))
; prints to console REPL
; --> java.lang.NullPointerException: Cannot invoke "Object.getClass()" because "target" is null
这段代码
- 打印到控制台 REPL
- 以上述异常结束
当我使用
(.start (Thread. pl100))
; --> prints to the console REPL
; --> runs with no errors
这段代码
- 打印到控制台 REPL
- 运行没有错误
当我使用
(.start (Thread. (pl-n 100)))
; --> prints to Atom REPL, not console REPL!
; ends with exception
; Execution error (NullPointerException) at java.lang.Thread/<init> (Thread.java:396).
; name cannot be null
; class java.lang.NullPointerException
这段代码
- 打印到 Atom REPL(我使用的是 Atom,而不是 emacs)!不像其他人那样去控制台 REPL
- 以异常结束
所以,有人可以帮我理解:
- 为什么当我运行一个需要输入的函数时,Java 会出错?为什么函数调用不等价?
- (.run ...) 在做什么?
- 为什么有时代码会打印到控制台,而有时会打印到 Atom/Chlorine?
解决方案
简而言之: Thread.run
需要一个功能。你的第一个展览给了它一个功能,pl100
,并按你期望的那样工作:
#(.run pl100)
.run
如果你给出的不是函数,而是调用函数返回的值,那么会发生完全不同的事情pl100
。事实上,pl100
返回 nil,所以Thread.run
会抛出 NullPointerException:
#(.run (pl100)) ;; NullPointerException
这就解释了为什么你的第二个展览没有达到你的预期。 pl-n
返回 nil,然后当您将 nil 传递给时出现异常Thread.run
:
#(.run (pl-n 100)) ;; NullPointerException
为了弥合差距 -Thread.run
需要无参数的函数和pl-n
需要参数的函数,您可以引入一个无参数的函数(以满足Thread.run
),它pl-n
使用所需的参数调用。习惯上这将是一个匿名函数。不幸的是,您不能嵌套#()
在其中#()
,因此您必须(fn [] ...)
对其中一个匿名函数使用更冗长的语法,很可能是外部函数。
推荐阅读
- ubuntu - 与 Kubernetes 和 SEtup 相关的难点
- javascript - 仅在加载 DOM 后如何使用 EvaluateScriptAsync() 返回值
- symfony - 如何通过 Symfony 中的鉴别器列加入 Doctrine DQL
- hibernate - hibernate批量插入的配置问题
- angular - 如何从通过指令(FormControlName)过滤的@ViewChildren 子集获取 ViewContainerRef?
- python - ModuleNotFoundError:没有名为“数学”的模块
- python - 如何使用 matplotlib 绘制与比例无关的箭头
- price - 亚马逊产品 API 不返回已履行的报价
- sql-server - 如何加入 JSON 以通过主键更新多行
- c++ - 使用连接的套接字终止 QWebSocketServer