日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

高并发编程-捕获线程运行时的异常 + 获取调用链

發布時間:2025/3/21 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 高并发编程-捕获线程运行时的异常 + 获取调用链 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 概述
  • 捕獲線程運行時的異常
    • 使用場景
    • UncaughtExceptionHandler 接口
    • 示例
  • 獲取調用鏈
  • 使用線程池的場景: 獲取線程運行時異常

概述


捕獲線程運行時的異常

我們看下Thread的定義 實現了Runnable接口

重寫了run方法


根據方法簽名可知,run方法是不能向上層拋出異常的,如果線程內部產生異常, 不catch的情況下,上層調用代碼如何知道呢?


使用場景

為啥需要這樣做呢?

一個線程拋出異常之后,只會在控制臺打印堆棧信息,即使有日志記錄,因為程序捕獲不到異常,只會在控制臺打出,并不是在日志記錄中出現。

所以,除非在線程拋出異常的時候,你剛好在觀察控制臺輸出的日子,看到了堆棧信息,否則,很難找到線程是哪里拋出了異常。

所以上面我們說到的捕獲線程內異常,就有用了,正常情況下,我們捕獲不到線程內的異常,但是我們可以通過 UncaughtExceptionHandler 來進行捕獲異常。并在在Handler中打印出錯誤日志,方便定位排查問題。


UncaughtExceptionHandler 接口

先看下 Thread類中的UncaughtExceptionHandler接口


示例

兩個線程,一個線程一直運行 ,另外一個線程有異常(一個數組下標越界異常,一個OOM異常 )

這里用OOM來演示

JVM參數設置: -Xms10m -Xmx10m

package com.artisan.test;import java.util.ArrayList; import java.util.Arrays; import java.util.List;public class CaughtThreadExceptionDemo {public static void main(String[] args) {List list = Arrays.asList(1, 2, 3);// 模擬線程一 拋出異常 被終止Thread t = new Thread(() -> {try {Thread.sleep(2_000); // list.get(99);List list2 = new ArrayList();for (int i = 0; i < Integer.MAX_VALUE; i++) {list2.add(i + "biubiubiubiubiubiubiubiubiubiubiubiu");}} catch (InterruptedException e) { // 這個地方不要捕獲 ArrayIndexOutOfBoundsException ,否則setUncaughtExceptionHandler無法捕獲到該異常System.out.println(Thread.currentThread().getName() + " some error happened....");e.printStackTrace();}}, "TEST_THREAD_1");// 線程啟動之前setUncaughtExceptionHandlert.setUncaughtExceptionHandler((thread, e) -> {System.out.println(" UncaughtExceptionHandler handle...." + e);System.out.println(" UncaughtExceptionHandler handle...." + thread.getName());});t.start();// 線程二 一直運行new Thread(() -> {while (true) {try {Thread.sleep(10_000);System.out.println(Thread.currentThread().getName() + " working...");} catch (InterruptedException e) {e.printStackTrace();}}}, "TEST_THREAD_2").start();} }

輸出

注意事項

  • 要處理的異常,不要被run方法中的catch捕獲(如果有catch的話)
  • setUncaughtExceptionHandler 在 start之前調用

  • 獲取調用鏈

    假設線程拋出如上異常,我們想記錄下更多的信息到DB或者其他存儲介質中,那如何打印出類似上面的信息呢?

    答案就是: getStackTrace() ,然后把它的輸出獲取出來 。

    示例如下:

    package com.artisan.test;import java.util.Arrays; import java.util.Optional;public class StackTraceDemo {public static void main(String[] args) {Test1 test1 = new Test1();test1.test1();}static class Test1 {public void test1() {new Test2().test2();}}static class Test2 {public void test2() {// Thread.currentThread().getStackTrace() 數組 轉 List// List stream ,然后過濾掉本地方法,最后遍歷 輸出Arrays.asList(Thread.currentThread().getStackTrace()).stream()// 過濾掉native方法.filter(element -> !element.isNativeMethod()).forEach(element -> Optional.of(element.getClassName() + ":" + element.getMethodName() + ":" + element.getLineNumber()).ifPresent(System.out::println));}} }

    輸出如下:


    使用線程池的場景: 獲取線程運行時異常

    戳這里

    總結

    以上是生活随笔為你收集整理的高并发编程-捕获线程运行时的异常 + 获取调用链的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。