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

标签 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)

这是我预期的行为。

但是现在如果我删除 future 的取消引用:
(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 被执行(否则“哎哟……”不会被打印出来),然后显然会抛出一个异常(否则“我们永远不会到达这里”会打印出来)……但是找不到那个异常,并且程序继续,好像一切都很好。

显然,只要我不尝试取消对 future 的引用,线程就可以在其工作中间(在这种情况下打印到标准输出)默默地死亡,并且无处可寻。

这是正常的吗?

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

什么是让 future 完成其工作(例如,从队列中消费消息)并在出现问题时“警告”我的惯用方式?

我应该将以后的每个调用都包装在 try/catch 块中吗?

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

我不应该使用 future 运行“不间断”线程吗?

基本上,我对 Java/Clojure 在这里的行为感到非常困惑,并且想要解释它为什么会这样,以及我应该如何处理这个问题。

最佳答案

在 clojure future是一个产生具体化 java.util.concurrent.Future 的宏,并取消引用它调用 Future.get方法。该方法可以抛出 ExecutionException它代表线程中未捕获的异常。因此,如果您不取消引用,则不会调用 .get你没有得到异常(exception)。

clojure doc 站点有源码,所以你可以看到实际的实现 here .

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

关于exception - 未捕获的异常在线程中如何表现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22496138/

相关文章:

vim - Clojure 中的 Slurpage 和 Barfage

asp.net-mvc - 从 Asp.net core 中的日志记录中排除自定义异常类

ios - 带有 UIWebview 的“NSUnknownKeyException”

android - Google Analytics Android SDK/异常报告 : "myParser represents your implementation of ExceptionParser"

oracle - 存储过程性能 : DataNotFound or External Cursor

java - Apache Storm 错误无法在本地集群上提交拓扑

python - 如何查看 Python 脚本中的错误或异常?

c# - 错误处理 我应该抛出异常吗?还是源头处理?

c# - .NET 错误处理

java - Clojure 的 require 函数中的别名不起作用