最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java如何主動從當(dāng)前線程獲取異常信息

 更新時間:2022年10月28日 09:35:04   作者:極光雨雨  
這篇文章主要介紹了Java如何主動從當(dāng)前線程獲取異常信息,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

Java主動從當(dāng)前線程獲取異常信息

使用場景

在單個方法內(nèi)主動捕獲異常,并將異常的錯誤棧信息以日志的方式打出來

寫法

當(dāng)前方法throw 了 異常,即改方法存在異常的情況,則可以使用如下方式獲取當(dāng)前線程中的異常:

// 主動獲取當(dāng)前線程異常棧信息
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();

// 以日志的方式打出 ?\n ?每一行錯誤棧信息結(jié)束后換行
log.error(StringUtils.join(stackTraceElements, '\n'));

Java捕獲并處理線程異常:Thread及ThreadPoolExecutor線程池異常捕獲

通過Thread.UncaughtExceptionHandler捕獲線程異常

Thread.UncaughtExceptionHandler類的作用:捕獲并處理線程run方法拋出的異常。

使用示例

為單個線程設(shè)置異常捕獲

Thread.UncaughtExceptionHandler exceptionHandler = (t, e) -> {
? ? System.out.println("報錯線程:" + t.getName());
? ? System.out.println("線程拋出的異常:" + e);
};
Thread thread = new Thread(() -> {
? ? throw new RuntimeException("throw a new Exception ! ");
});
thread.setUncaughtExceptionHandler(exceptionHandler); // 設(shè)置異常處理器
thread.start();

如果項目中,全局的Thread線程處理異常的方式都相同,那么可以設(shè)置一個全局的異常捕獲類。

Thread.UncaughtExceptionHandler exceptionHandler = (t, e) -> {
? ? System.out.println("報錯線程:" + t.getName());
? ? System.out.println("線程拋出的異常:" + e);
};
Thread.setDefaultUncaughtExceptionHandler(exceptionHandler);

通過這種方式,后續(xù)的Thread都可以公用這個異常處理類。如果需要用其它方式處理異常時,只需要實(shí)現(xiàn)1中的內(nèi)容即可。

部分源碼解析

UncaughtExceptionHandler源碼
// Thread.UncaughtExceptionHandler?
@FunctionalInterface
public interface UncaughtExceptionHandler {
? ? void uncaughtException(Thread t, Throwable e);
}

Thread中的UncaughtExceptionHandler屬性

// 作用于當(dāng)個Thread線程
private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
// static修飾,其可以作用于所有Thread線程
private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;

在Thread中,會首先提供Thread私有的異常處理類,然后才是全局

public UncaughtExceptionHandler getUncaughtExceptionHandler() {
? ? return uncaughtExceptionHandler != null ?
? ? ? ? uncaughtExceptionHandler : group;
}

實(shí)現(xiàn)原理

當(dāng)線程由于未捕獲的異常而即將終止時,Java虛擬機(jī)將使用調(diào)用線程的getUncaughtExceptionHandler方法,以此來獲取UncaughtExceptionHandler類,并執(zhí)行其對異常的處理方法。

如果一個線程沒有顯式實(shí)現(xiàn)UncaughtExceptionHandler ,那么它的ThreadGroup對象將充當(dāng)它的UncaughtExceptionHandler類。

// Thread#getUncaughtExceptionHandler
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
? ? return uncaughtExceptionHandler != null ?
? ? ? ? uncaughtExceptionHandler : group;
}

ThreadGroup實(shí)現(xiàn)了UncaughtExceptionHandler類。

public class ThreadGroup implements Thread.UncaughtExceptionHandler {
?? ?// ……
?? ?public void uncaughtException(Thread t, Throwable e) {
?? ??? ?// 父級ThreadGroup的處理方法
?? ? ? ?if (parent != null) {
?? ? ? ? ? ?parent.uncaughtException(t, e);
?? ? ? ?} else {
?? ? ? ??? ?// Thread 的全局默認(rèn)處理方法
?? ? ? ? ? ?Thread.UncaughtExceptionHandler ueh =
?? ? ? ? ? ? ? ?Thread.getDefaultUncaughtExceptionHandler();
?? ? ? ? ? ?if (ueh != null) {
?? ? ? ? ? ? ? ?ueh.uncaughtException(t, e);
?? ? ? ? ? ?} else if (!(e instanceof ThreadDeath)) {
?? ? ? ? ? ? ? ?System.err.print("Exception in thread \""
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? + t.getName() + "\" ");
?? ? ? ? ? ? ? ?e.printStackTrace(System.err);
?? ? ? ? ? ?}
?? ? ? ?}
?? ?}
?? ?// ……
}

ThreadPoolExecutor線程池異常捕獲

使用示例

要捕獲ThreadPoolExecutor線程池中的線程執(zhí)行異常,需要實(shí)現(xiàn)被protected修飾的方法afterExecute,在該方法里面處理異常即可。

// ThreadPoolExecutor#afterExecute
class ExtendedExecutor extends ThreadPoolExecutor {
? protected void afterExecute(Runnable r, Throwable t) {
? ? super.afterExecute(r, t);
? ? // 如果Runnable是Future類型,那么異常將會直接通過Future返回
? ? if (t == null && r instanceof Future<?>) {
? ? ? try {
? ? ? ? Object result = ((Future<?>) r).get();
? ? ? } catch (CancellationException ce) {
? ? ? ? ? t = ce;
? ? ? } catch (ExecutionException ee) {
? ? ? ? ? t = ee.getCause();
? ? ? } catch (InterruptedException ie) {
? ? ? ? ? Thread.currentThread().interrupt(); // ignore/reset
? ? ? }
? ? }
? ? // 非Future類型
? ? if (t != null)
? ? ? System.out.println(t);
? }
}

注意:實(shí)現(xiàn)afterExecute方法時,要正確嵌套多個覆蓋,子類通常應(yīng)在此方法的開頭調(diào)用super.afterExecute,以確保不會破壞其他父類方法的實(shí)現(xiàn)。

源碼解析

在ThreadPoolExecutor中,線程任務(wù)的實(shí)際執(zhí)行方法是runWorker,如下所示:

// ThreadPoolExecutor#runWorker
final void runWorker(Worker w) {
? ? Thread wt = Thread.currentThread();
? ? Runnable task = w.firstTask; // 實(shí)際提交的任務(wù)
? ? ? ? ? ? // …………
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? beforeExecute(wt, task); // task執(zhí)行前的操作
? ? ? ? ? ? ? ? Throwable thrown = null; // 異常信息保存
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? task.run(); // 執(zhí)行任務(wù)
? ? ? ? ? ? ? ? } catch (RuntimeException x) {
? ? ? ? ? ? ? ? ? ? thrown = x; throw x;
? ? ? ? ? ? ? ? } catch (Error x) {
? ? ? ? ? ? ? ? ? ? thrown = x; throw x;
? ? ? ? ? ? ? ? } catch (Throwable x) {
? ? ? ? ? ? ? ? ? ? thrown = x; throw new Error(x);
? ? ? ? ? ? ? ? } finally {
? ? ? ? ? ? ? ? ? ? afterExecute(task, thrown); // task執(zhí)行后的操作,也就包括了異常的捕獲工作
? ? ? ? ? ? ? ? }
? ? ? ? ? ? } finally {
? ? ? ? ? ? ? ? task = null;
? ? ? ? ? ? ? ? w.completedTasks++;
? ? ? ? ? ? ? ? w.unlock();
? ? ? ? ? ? }
? ? ? ? // ……
}

afterExecute方法在ThreadPoolExecutor,并沒有進(jìn)行任何操作,就是對異常的線程靜默處理

// ThreadPoolExecutor#afterExecute
protected void afterExecute(Runnable r, Throwable t) { }

Callable類型的任務(wù),在執(zhí)行時會自己捕獲并維護(hù)執(zhí)行中的異常。 

// AbstractExecutorService#submit
public <T> Future<T> submit(Callable<T> task) {
? ? if (task == null) throw new NullPointerException();
? ? RunnableFuture<T> ftask = newTaskFor(task);
? ? execute(ftask);
? ? return ftask;
}

// Callable任務(wù)會被封裝成FutureTask
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
? ? return new FutureTask<T>(callable);
}

在FutureTask的run方法中,他們內(nèi)部會將整個任務(wù)用try-catch給包起來。因此,也不會拋出Callable#run執(zhí)行的內(nèi)部異常。

// FutureTask#run
public void run() {
?? ?// ……
? ? try {
? ? ? ? Callable<V> c = callable;
? ? ? ? // ……
? ? ? ? ? ? // 這里將Callable的執(zhí)行過程產(chǎn)生的異常都捕獲了
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? result = c.call();
? ? ? ? ? ? ? ? ran = true;
? ? ? ? ? ? } catch (Throwable ex) {
? ? ? ? ? ? ? ? result = null;
? ? ? ? ? ? ? ? ran = false;
? ? ? ? ? ? ? ? setException(ex);
? ? ? ? ? ? }
? ? ? ? ? ? if (ran)
? ? ? ? ? ? ? ? set(result);
? ? ? ? }
? ? } finally {
// ……

以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Maven 打包項目到私服 (deploy)的配置方法

    Maven 打包項目到私服 (deploy)的配置方法

    這篇文章主要介紹了Maven 打包項目到私服 (deploy)的配置方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • Mybatis有查詢結(jié)果但存不進(jìn)實(shí)體類的解決方案

    Mybatis有查詢結(jié)果但存不進(jìn)實(shí)體類的解決方案

    這篇文章主要介紹了Mybatis有查詢結(jié)果但存不進(jìn)實(shí)體類的解決方案,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • java interface的兩個經(jīng)典用法

    java interface的兩個經(jīng)典用法

    這篇文章主要為大家詳細(xì)介紹了java interface的兩個經(jīng)典用法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • Java?使用geotools讀取tiff數(shù)據(jù)的示例代碼

    Java?使用geotools讀取tiff數(shù)據(jù)的示例代碼

    這篇文章主要介紹了Java?通過geotools讀取tiff,一般對于tiff數(shù)據(jù)的讀取,都會借助于gdal,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-04-04
  • Java實(shí)現(xiàn)JSON與XML相互轉(zhuǎn)換的簡明教程

    Java實(shí)現(xiàn)JSON與XML相互轉(zhuǎn)換的簡明教程

    Java實(shí)現(xiàn)復(fù)雜數(shù)據(jù)結(jié)構(gòu)(如嵌套對象、數(shù)組)在 JSON 與 XML 之間的相互轉(zhuǎn)換,可以使用 Jackson 和 Jackson XML 擴(kuò)展庫來完成,Jackson 是一個流行的 JSON 處理庫,通過 Jackson 的 XML 擴(kuò)展庫,可以實(shí)現(xiàn) JSON 和 XML 之間的轉(zhuǎn)換,需要的朋友可以參考下
    2024-08-08
  • java導(dǎo)出dbf文件生僻漢字處理方式

    java導(dǎo)出dbf文件生僻漢字處理方式

    這篇文章主要介紹了java導(dǎo)出dbf文件生僻漢字處理方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • SpringBoot Actuator監(jiān)控的項目實(shí)踐

    SpringBoot Actuator監(jiān)控的項目實(shí)踐

    本文主要結(jié)合 Spring Boot Actuator,跟大家一起分享微服務(wù)Spring Boot Actuator 的常見用法,方便我們在日常中對我們的微服務(wù)進(jìn)行監(jiān)控治理,感興趣的可以了解一下
    2024-01-01
  • 8個Spring事務(wù)失效場景詳解

    8個Spring事務(wù)失效場景詳解

    相信大家對Spring種事務(wù)的使用并不陌生,但是你可能只是停留在基礎(chǔ)的使用層面上。今天,我們就簡單來說下Spring事務(wù)的原理,然后總結(jié)一下spring事務(wù)失敗的場景,并提出對應(yīng)的解決方案,需要的可以參考一下
    2022-12-12
  • Java程序死鎖問題定位與解決方法

    Java程序死鎖問題定位與解決方法

    死鎖是一種特定的程序狀態(tài),主要是由于循環(huán)依賴導(dǎo)致彼此一直處于等待中,而使得程序陷入僵局,相當(dāng)尷尬,死鎖不僅僅發(fā)生在線程之間,而對于資源獨(dú)占的進(jìn)程之間同樣可能出現(xiàn)死鎖,本文給大家介紹了Java程序死鎖問題定位與解決方法,需要的朋友可以參考下
    2024-11-11
  • Mybatis中強(qiáng)大的resultMap功能介紹

    Mybatis中強(qiáng)大的resultMap功能介紹

    這篇文章主要給大家介紹了關(guān)于Mybatis中強(qiáng)大的resultMap功能的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Mybatis具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06

最新評論

桂东县| 合水县| 桦川县| 土默特右旗| 佳木斯市| 潼南县| 广宗县| 固始县| 尼木县| 武川县| 隆安县| 乐安县| 财经| 五家渠市| 永清县| 长武县| 甘南县| 治县。| 雷山县| 淳安县| 张家口市| 呼伦贝尔市| 昭通市| 遵义市| 延庆县| 响水县| 阜康市| 香格里拉县| 宜都市| 元阳县| 东阿县| 外汇| 塔河县| 广水市| 政和县| 大田县| 青海省| 太康县| 汨罗市| 渝中区| 宁强县|