1. 程式人生 > 實用技巧 >捕獲執行緒執行期間的異常

捕獲執行緒執行期間的異常

捕獲執行緒執行期間的異常

上一篇文章我們學習了在我們使用application的時候在他出現問題或者人為終止的時候,我們怎麼有機會捕獲異常或者人為的做一些操作,比如寫一些日誌,或者傳送一個RESTful或者關閉釋放一些資源,那麼執行緒執行期間的異常該如何捕獲呢?我們知道執行緒的執行邏輯單元在run方法裡,run方法的簽名是不允許丟擲異常的,今天我們就來學習一下執行緒的Exception。
先來一段丟擲異常的程式碼:

public class ThreadException {
    private final static int A = 10;
    private static final int B = 0;

    public static void main(String[] args) {
        /// 捕獲執行緒執行期間的異常
        Thread t = new Thread(() -> {
            try {
                Thread.sleep(1_000L);
                int result = A / B;
                System.out.println("result = " + result);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t.start();
    }
}

執行效果如下:

我們改造一下我們的程式碼,Thread物件提供了setUncaughtExceptionHandler方法用來獲取執行緒中產生的異常。而且建議使用該方法為執行緒設定異常捕獲方法:

t.setUncaughtExceptionHandler((thread, e) -> {
    System.out.println(e);
    System.out.println(thread.getName());
    System.out.println(thread.getThreadGroup().getName());
    System.out.println(thread.getThreadGroup().getParent().getName());
});

執行效果如下:

可以看到異常的詳細堆疊資訊已經打印出來了,下面做個實驗來輸出一下,先建幾個類分別進行呼叫,如下:

public class ThreadException {
    public static void main(String[] args) {
        // stack trace
        new Test1().test();
    }
}
public class Test1 {
    private Test2 test2 = new Test2();

    public void test() {
        test2.test();
    }
}
public class Test2 {
    public void test() {
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        Stream.of(stackTrace)
                .filter(e -> !e.isNativeMethod())
                .forEach(e ->
                        Optional.of(e.getClassName() + "." + e.getMethodName() + ":" + e.getLineNumber())
                                .ifPresent(System.out::println)
                );

    }
}

執行效果如下:

這個在後續使用中有補充再繼續補充,後面開始學習ThreadGroupApI的學習,然後實現一個執行緒池,java併發程式設計的基礎就碼一遍了。