【发布时间】:2014-03-19 15:28:35
【问题描述】:
我试图了解一个程序发生了什么,其中我有异常“消失”而没有任何通知(并且线程停止工作)。
我能想出的重现该问题的最简单情况是:
(defn -main []
(let [a (future (do (println "Ouch... ")
(/ 0 0)
(println "We never arrive here")))]
(Thread/sleep 1000)
(println "Hmmmm" @a)))
果然,在 repl 上运行(或使用 lein run)时,我得到一个异常:
so.core> (-main)
Ouch...
ArithmeticException Divide by zero clojure.lang.Numbers.divide (Numbers.java:156)
这是我预期的行为。
但是现在如果我删除未来的取消引用:
(defn -main []
(let [a (future (do (println "Ouch... ")
(/ 0 0)
(println "We never arrive here")))]
(Thread/sleep 1000)
(println "Hmmmm")))
这是输出:
so.core> (-main)
Ouch...
Hmmmm
nil
so.core>
所以 future 被执行(否则 “Ouch...” 不会被打印)并且显然会抛出异常(否则 “我们永远不会到达这里” 会打印)...但是找不到那个异常,程序继续运行,好像一切都很好。
显然,只要我不尝试取消对未来的引用,线程就可以在它的工作中间默默地死掉(在这种情况下打印到标准输出),并且找不到异常。
这正常吗?
我是否应该在我的 Emacs / cider 缓冲区之一中找到该异常的(堆栈)跟踪?
什么是让未来完成其工作(例如使用队列中的消息)并在出现问题时“警告”我的惯用方式?
我应该将以后的每个调用都包装在 try/catch 块中吗?
我应该设置一个默认的未捕获异常处理程序吗?
我不应该使用未来运行“不间断”线程吗?
基本上,我对 Java/Clojure 的行为感到非常困惑,并且希望能够解释 为什么 它的行为方式以及 如何应该解决这个问题。
【问题讨论】:
标签: exception exception-handling clojure future