未捕获的异常如何在线程中表现?

时间:2014-03-19 04:21:18

标签: exception exception-handling clojure future

我试图了解一个程序正在发生什么事情,我有例外情况"正在消失"没有任何通知(线程停止工作)。

我能想出的最简单的问题是:

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

所以未来会被执行(否则" Ouch ......" 不会被打印)显然会抛出异常(否则& #34;我们永远不会到达这里" 会打印)...但是这个例外无处可寻,程序仍在继续,好像一切都很好。

显然只要我不尝试取消引用未来,线程就可以在其工作中间(在这种情况下打印到stdout)静默地死亡,并且无处可寻找异常。 / p>

这是正常的吗?

我是否应该在我的一个Emacs / cider缓冲区中找到该异常的(堆栈)跟踪?

让未来完成其工作的惯用方法是什么(例如,从队列中消费消息)然后"警告"什么时候出错了我?

我应该在try / catch块中包装每个未来的调用吗?

我应该设置默认的未捕获异常处理程序吗?

我不应该不停地跑步#34;线程使用未来?

基本上我对这里的Java / Clojure的行为非常困惑,并且想要解释为什么它的行为方式和如何< / em>我应该处理这个问题。

1 个答案:

答案 0 :(得分:6)

在clojure中future是一个生成具体化java.util.concurrent.Future的宏,取消引用它会调用Future.get方法。该方法可以抛出ExecutionException,表示线程中未捕获的异常。因此,如果您不取消引用,则不要调用.get,也不会获得异常。

clojure doc网站有源代码,因此您可以看到实际的实现here

如果您不想取消引用,我认为您应该在帖子中try / catch,并以您选择的任何方式处理。