2014-03-19 17 views
4

我試圖理解程序中發生了什麼,我有異常「消失」,沒有任何通知(和一個線程停止工作)。未捕獲的異常如何在線程中表現?

我可以拿出來重現問題最簡單的情況是這樣的:

(defn -main [] 
    (let [a (future (do (println "Ouch... ") 
         (/ 0 0) 
         (println "We never arrive here")))] 
     (Thread/sleep 1000) 
     (println "Hmmmm" @a))) 

毫無疑問的是,當在REPL運行(或使用雷音運行),我得到一個異常:

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> 

所以在執行未來的(否則「哎喲......」止跌」 )然後拋出一個異常(否則「我們永遠不會到達這裏」會打印)......但是這個異常無處可尋,程序繼續,好像一切都很好。

顯然只要我不試圖解引用未來,線程可以靜靜地死掉,在它的工作中(在這種情況下打印到標準輸出),並且無處可尋。

這是正常的嗎?

我是否應該在Emacs/cider緩衝區之一中找到該異常的(堆棧)跟蹤?

如果將來有工作(例如,從隊列中消費消息)並在出現問題時「發出警告」,這會是一種慣用的方式嗎?

我應該在try/catch塊內包裝每一個未來的調用嗎?

我應該設置一個默認的未捕獲異常處理程序嗎?

我不應該使用未來運行「不停止」線程嗎?

基本上我在Java/Clojure的,這裏的行爲很迷茫,想有兩種解釋,爲什麼它的表現如何,我應該處理這個問題,這種方式和

回答

6

在clojure future是一個宏,產生一個具體化的java.util.concurrent.Future,並取消它引用Future.get方法。該方法可以拋出ExecutionException這表示線程中未捕獲的異常。所以,如果你不取消引用,你不要打電話.get,你沒有得到例外。

clojure doc站點有源碼,所以你可以看到實際的實現here

如果你不想解除引用,我想你應該try/catch在線程中,並以任何你選擇的方式處理。

+0

小點,但Clojure未來*是*未來,而不是包裝。 –

+0

改進了更具體的答案 – Kevin

相關問題