捕獲異常終止的線程信息

單線程的開發過程中,通常採用try-catch的方式進行異常捕獲,但是這種方式在多線程環境中會顯得無能爲力,而且還有可能導致一些問題的出現,比如發生異常的時候不能及時回收系統資源,或者無法及時關閉當前的連接

概述

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();
    }
}

控制檯輸出異常:

Exception in thread "T2" java.lang.NumberFormatException: For input string: "ABC"
	at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.lang.Integer.parseInt(Integer.java:580)
	at java.lang.Integer.parseInt(Integer.java:615)
	at com.demo.sso.resource1.test.ThreadUncaughtException.lambda$main$0(ThreadUncaughtException.java:18)
	at java.lang.Thread.run(Thread.java:748)

分析: 從日誌中,並未發現關閉資源應有的日誌輸出,很明顯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中就有使用過,源碼爲:ZookeeperThreadZooKeeperCriticalThread

 

 

本文鏈接: https://blog.battcn.com/2017/10/11/java/thread/thread-uncaught-exception/

作者二維碼:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章