Exception 未捕获异常在线程中的行为如何?

Exception 未捕获异常在线程中的行为如何?,exception,exception-handling,clojure,future,Exception,Exception Handling,Clojure,Future,我正在试图理解一个程序发生了什么,在这个程序中,我的异常在没有任何通知的情况下“消失”(线程停止工作) 我能想出的重现这个问题的最简单的例子是: (defn -main [] (let [a (future (do (println "Ouch... ") (/ 0 0) (println "We never arrive here")))] (Thread/sleep 1000)

我正在试图理解一个程序发生了什么,在这个程序中,我的异常在没有任何通知的情况下“消失”(线程停止工作)

我能想出的重现这个问题的最简单的例子是:

(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> 
因此,未来将被执行(否则“哎哟…”将不会被打印),然后显然会抛出一个异常(否则“我们永远不会到达这里”将被打印)。。。但这一例外却无处可寻,该计划继续进行,似乎一切都很好

显然,只要我不试图取消对未来的引用,线程就可以悄无声息地死去,在其工作的中间(在这种情况下,打印到STDUT),并且异常没有找到。 这正常吗

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

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

我是否应该将未来的每一个调用都封装在try/catch块中

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

我不应该使用future运行“不停止”线程吗


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

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

clojure文档站点有源代码,因此您可以看到实际的实现


如果您不想取消引用,我想您应该
尝试
/
在线程中捕获
,并以您选择的任何方式进行处理。

这点很小,但Clojure future是一个未来,而不是包装器。改进了答案,使其更加具体