在
單線程
的開發過程當中,一般採用try-catch
的方式進行異常捕獲,可是這種方式在多線程環境
中會顯得無能爲力
,並且還有可能致使一些問題的出現,好比發生異常的時候不能及時回收系統資源
,或者沒法及時關閉當前的鏈接
...java
<!-- more -->git
Java中有兩種異常,即已知異常(編輯器會提示捕獲或者拋出)
和未知異常(特殊狀況下發生)
,因爲線程中的run()
方法是不接受拋出語句的(只能內部捕獲),因此在面對未知異常
的狀況,線程默認的會將堆棧跟蹤信息輸出到控制檯中(或者記錄到錯誤日誌文件中)而後退出程序。微信
在JDK1.5
以前,不能爲線程單獨設置或指定一個默認的UncaughtExceptionHandler
,爲了設置UncaughtExceptionHandler
,須要繼承ThreadGroup
並覆寫uncaughtException
方法。 幸運的是JDK1.5
後線程提供了一個setUncaughtExceptionHandler
方法,用來捕獲並處理因線程中拋出的未知異常
,以免程序終止。多線程
1.首先模擬一個鏈接池,提供異步
class ConnectionPool { static void create() { System.out.println("初始化鏈接池..."); } static void close() { System.out.println("關閉鏈接池..."); } }
2.爲了測試須要,只是簡單模擬了一個異常編輯器
public static void main(String[] args) { ConnectionPool.create(); try { //有個任務須要異步執行 Thread thread = new Thread(() -> System.out.println(Integer.parseInt("ABC")), "T2"); thread.start(); } catch (Exception e) { ConnectionPool.close(); } }
分析: 從日誌中,並未發現關閉資源應有的日誌輸出,很明顯try-catch
沒有起做用,由於在main函數中
他是主線程
,當thread.start()
以後,主線程
的代碼與子線程
就沒半毛錢關係了,因此發生在子線程
內部的錯誤沒法捕獲到。函數
使用
UncaughtExceptionHandler
,這裏爲了偷懶使用了lambda
簡化了匿名內部類的寫法(也能夠實現UncaughtExceptionHandler
)測試
public static void main(String[] args) { ConnectionPool.create(); Thread thread = new Thread(() -> System.out.println(Integer.parseInt("ABC")), "T1"); thread.start(); thread.setUncaughtExceptionHandler((t, e) -> { System.out.println("[線程] - [" + t.getName() + "] - [消息] - [" + e.getMessage() + "]"); ConnectionPool.close(); }); }
分析: 從日誌中能夠發現錯誤信息被咱們捕獲了,而且能夠成功釋放資源!使用UncaughtExceptionHandler
,能夠捕獲到未知異常
且記錄下自定義的日誌(默認拋出堆棧信息),具體在Zookeeper
中就有使用過,源碼爲:ZookeeperThread
,ZooKeeperCriticalThread
,有興趣能夠去看看...spa
微信公衆號:battcn
(歡迎調戲)