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

在自定義線程池中捕獲和處理異常實(shí)現(xiàn)過(guò)程

 更新時(shí)間:2026年05月14日 09:59:13   作者:北執(zhí)南念  
這篇文章主要介紹了在自定義線程池中捕獲和處理異常實(shí)現(xiàn)過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

1. MyUncaughtExceptionHandler 類

這是一個(gè)自定義的未捕獲異常處理器,當(dāng)線程因?yàn)槲床东@異常而終止時(shí),就會(huì)調(diào)用這個(gè)處理器。它會(huì)記錄錯(cuò)誤日志,并且可以添加像通知開發(fā)人員等額外的處理邏輯。

package com.hy.archive.config;

import lombok.extern.slf4j.Slf4j;

/**
 * Description: 自定義處理器
 *  這是一個(gè)自定義的未捕獲異常處理器,當(dāng)線程因?yàn)槲床东@異常而終止時(shí),就會(huì)調(diào)用這個(gè)處理器。
 *
 * @Author Js
 * @Create 2025-07-08 20:04
 * @Version 1.0
 */
@Slf4j
public class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        log.error("Exception in thread :" + e);
        // do something
        //記錄日志、告警企業(yè)微信釘釘通知開發(fā)
    }
}

使用說(shuō)明:一般不會(huì)直接調(diào)用這個(gè)類,而是通過(guò)線程工廠自動(dòng)設(shè)置到線程上。

2. MyThreadFactory 類

這是一個(gè)自定義的線程工廠,其作用是對(duì)原生線程工廠進(jìn)行包裝。它會(huì)為每個(gè)新創(chuàng)建的線程設(shè)置一個(gè)自定義的未捕獲異常處理器,也就是MyUncaughtExceptionHandler。

package com.hy.archive.config;

import java.util.concurrent.ThreadFactory;

/**
 * Description: 自定義線程工廠處理
 *
 * @Author Js
 * @Create 2025-07-08 20:01
 * @Version 1.0
 */
public class MyThreadFactory implements ThreadFactory {

    private final ThreadFactory original;


    public MyThreadFactory(ThreadFactory original) {
        this.original = original;
    }


    @Override
    public Thread newThread(Runnable r) {
        Thread thread = original.newThread(r);
        // 異常捕獲
        thread.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());//自定義的未捕獲異常處理器
        return thread;
    }
}

使用說(shuō)明:在配置線程池時(shí),把這個(gè)工廠傳遞給線程池,這樣線程池創(chuàng)建的所有線程都會(huì)具備異常捕獲能力。

3. ThreadPoolConfig 類

這是一個(gè) Spring 配置類,用于創(chuàng)建和配置一個(gè)名為accountExecutor的線程池。

package com.hy.archive.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 自定義單列線程池配置類
 */
@Configuration
@EnableAsync
public class ThreadPoolConfig implements AsyncConfigurer {

    //自定義線程池名稱
    public static final String ACCOUNT_EXECUTOR = "accountExecutor";

    @Override
    public Executor getAsyncExecutor() {
        return accountExecutor();
    }

    @Bean(ACCOUNT_EXECUTOR)
    @Primary
    public ThreadPoolTaskExecutor accountExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(500);
        // 線程池優(yōu)雅停機(jī)的關(guān)鍵
        executor.setWaitForTasksToCompleteOnShutdown(true);
        // 線程池前綴配置
        executor.setThreadNamePrefix("account-exec-");
        //滿了調(diào)用線程執(zhí)行,認(rèn)為重要任務(wù)
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //設(shè)置線程池的異常處理邏輯使用了裝飾器設(shè)計(jì)模式
        executor.setThreadFactory(new MyThreadFactory(executor));
        executor.initialize();
        return executor;

    }
}

4.舉個(gè)案例如何使用

1.異步使用

假設(shè)你有一個(gè)異步服務(wù),使用該線程池執(zhí)行任務(wù):

@Service
public class MyAsyncService {

    @Async("accountExecutor") // 指定使用自定義線程池
    public CompletableFuture<String> processAccount(String accountId) {
        // 模擬業(yè)務(wù)邏輯
        if (accountId == null) {
            throw new RuntimeException("賬戶ID不能為空"); // 未捕獲異常
        }
        // 正常業(yè)務(wù)邏輯...
        return CompletableFuture.completedFuture("處理完成");
    }
}

當(dāng)調(diào)用 processAccount(null) 時(shí),會(huì)觸發(fā)未捕獲異常,此時(shí)異常處理流程如下:

  • 線程池中的線程執(zhí)行任務(wù)時(shí)拋出 RuntimeException。
  • 由于線程已通過(guò) MyThreadFactory 設(shè)置了 MyUncaughtExceptionHandler,異常會(huì)被該處理器捕獲。
  • MyUncaughtExceptionHandler 記錄錯(cuò)誤日志(例如:Exception in thread account-exec-1: 賬戶ID不能為空)。
  • 可擴(kuò)展邏輯(如發(fā)送告警)被觸發(fā)。

2.結(jié)合 CompletableFuture

@Service
public class AccountService {

    @Autowired
    private ThreadPoolTaskExecutor accountExecutor; // 注入你的線程池

    public CompletableFuture<String> processAccount(String accountId) {
        return CompletableFuture.supplyAsync(() -> {
            // 模擬業(yè)務(wù)邏輯,可能拋出異常
            if (accountId == null) {
                throw new RuntimeException("賬戶ID不能為空");
            }
            // 正常處理邏輯...
            return "賬戶處理成功: " + accountId;
        }, accountExecutor) // 指定使用你的線程池
        .exceptionally(ex -> {
            // 處理異常的邏輯
            log.error("處理賬戶時(shí)發(fā)生異常: {}", ex.getMessage(), ex);
            return "處理失敗: " + ex.getMessage(); // 返回默認(rèn)值或錯(cuò)誤信息
        });
    }
}

異常處理機(jī)制說(shuō)明

  • supplyAsync + 指定線程池

使用 accountExecutor 線程池執(zhí)行異步任務(wù),該線程池已通過(guò)你的 MyThreadFactory 設(shè)置了 MyUncaughtExceptionHandler。

  • exceptionally 回調(diào)

當(dāng)任務(wù)拋出異常時(shí),exceptionally 會(huì)捕獲異常并返回默認(rèn)值或處理結(jié)果。這是 CompletableFuture 提供的顯式異常處理方式。

雙重保障

  • 若未使用 exceptionally,異常會(huì)被你的 MyUncaughtExceptionHandler 捕獲(記錄日志并觸發(fā)告警)。
  • 若使用 exceptionally,異常會(huì)被顯式處理,同時(shí) MyUncaughtExceptionHandler 仍會(huì)記錄日志(雙重保障)。

驗(yàn)證異常處理效果

@SpringBootTest
class AccountServiceTest {

    @Autowired
    private AccountService accountService;

    @Test
    void testExceptionHandling() throws Exception {
        // 模擬異常情況
        CompletableFuture<String> future = accountService.processAccount(null);
        
        // 驗(yàn)證異常處理結(jié)果
        String result = future.get(); // 不會(huì)拋出異常,因?yàn)閑xceptionally已處理
        assertEquals("處理失敗: 賬戶ID不能為空", result);
        
        // 檢查日志:MyUncaughtExceptionHandler也會(huì)記錄該異常
        // ERROR Exception in thread account-exec-1: 賬戶ID不能為空
    }
}

更復(fù)雜的異常處理鏈

CompletableFuture 提供了多種異常處理方法,可根據(jù)需求組合使用:

public CompletableFuture<String> processAccount(String accountId) {
    return CompletableFuture.supplyAsync(() -> {
        if (accountId == null) {
            throw new IllegalArgumentException("賬戶ID不能為空");
        }
        if (!isValid(accountId)) {
            throw new RuntimeException("賬戶ID無(wú)效");
        }
        return "賬戶處理成功: " + accountId;
    }, accountExecutor)
    .exceptionally(ex -> {
        if (ex instanceof IllegalArgumentException) {
            return "非法參數(shù): " + ex.getMessage();
        } else {
            return "系統(tǒng)錯(cuò)誤: " + ex.getMessage();
        }
    })
    .thenApply(result -> {
        // 繼續(xù)處理結(jié)果
        return "最終結(jié)果: " + result;
    })
    .exceptionally(ex -> {
        // 處理后續(xù)步驟可能出現(xiàn)的異常
        return "處理失敗: " + ex.getMessage();
    });
}

關(guān)鍵區(qū)別:CompletableFuture vs 普通異步任務(wù)

場(chǎng)景異常處理方式是否需要 MyUncaughtExceptionHandler
普通異步任務(wù) (@Async)依賴 MyUncaughtExceptionHandler 統(tǒng)一處理必須配置
CompletableFuture + exceptionally顯式捕獲并處理異常可選(用于日志記錄和額外監(jiān)控)
CompletableFuture + 未處理異常依賴 MyUncaughtExceptionHandler 捕獲必須配置

最佳實(shí)踐建議

優(yōu)先使用 CompletableFuture 的顯式處理

在異步任務(wù)中,盡量通過(guò) exceptionally()、handle()whenComplete() 顯式處理異常,使代碼更健壯。

保留統(tǒng)一異常處理器作為兜底

你的 MyUncaughtExceptionHandler 仍有價(jià)值,可用于記錄所有未被顯式處理的異常,避免遺漏問題。

區(qū)分可恢復(fù)異常和不可恢復(fù)異常

對(duì)不同類型的異常采取不同處理策略,例如:

.exceptionally(ex -> {
    if (ex instanceof RetryableException) {
        // 重試邏輯
        return retry(accountId);
    } else {
        // 記錄致命錯(cuò)誤并返回默認(rèn)值
        log.error("致命錯(cuò)誤", ex);
        return "默認(rèn)結(jié)果";
    }
})

總結(jié)

通過(guò)結(jié)合你的線程池配置和 CompletableFuture 的異常處理機(jī)制,你可以實(shí)現(xiàn):

  • 顯式異常處理:通過(guò) exceptionally 等方法直接處理已知異常。
  • 統(tǒng)一日志記錄:利用 MyUncaughtExceptionHandler 記錄所有異常,確保無(wú)遺漏。
  • 靈活的錯(cuò)誤恢復(fù):根據(jù)異常類型執(zhí)行不同的恢復(fù)邏輯。

這種組合方式既保證了代碼的健壯性,又便于問題追蹤和系統(tǒng)監(jiān)控。

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

相關(guān)文章

  • Mybatis之動(dòng)態(tài)SQL使用小結(jié)(全網(wǎng)最新)

    Mybatis之動(dòng)態(tài)SQL使用小結(jié)(全網(wǎng)最新)

    MyBatis令人喜歡的一大特性就是動(dòng)態(tài)SQL,?在使用JDBC的過(guò)程中,?根據(jù)條件進(jìn)行SQL的拼接是很麻煩且很容易出錯(cuò)的,MyBatis通過(guò)OGNL來(lái)進(jìn)行動(dòng)態(tài)SQL的使用解決了這個(gè)麻煩,對(duì)Mybatis動(dòng)態(tài)SQL相關(guān)知識(shí)感興趣的朋友跟隨小編一起看看吧
    2024-05-05
  • Java字符串技巧之刪除標(biāo)點(diǎn)或最后字符的方法

    Java字符串技巧之刪除標(biāo)點(diǎn)或最后字符的方法

    這篇文章主要介紹了Java字符串技巧之刪除標(biāo)點(diǎn)或最后字符的方法,是Java入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-11-11
  • Java toString方法重寫工具之ToStringBuilder案例詳解

    Java toString方法重寫工具之ToStringBuilder案例詳解

    這篇文章主要介紹了Java toString方法重寫工具之ToStringBuilder案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • springboot項(xiàng)目如何開啟https服務(wù)

    springboot項(xiàng)目如何開啟https服務(wù)

    這篇文章主要介紹了springboot項(xiàng)目如何開啟https服務(wù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • Python安裝Jupyter Notebook配置使用教程詳解

    Python安裝Jupyter Notebook配置使用教程詳解

    這篇文章主要介紹了Python安裝Jupyter Notebook配置使用教程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • 解決Spring?AOP攔截抽象類(父類)中方法失效問題

    解決Spring?AOP攔截抽象類(父類)中方法失效問題

    這篇文章主要介紹了解決Spring?AOP攔截抽象類(父類)中方法失效問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • SpringBoot啟動(dòng)過(guò)程逐步分析講解

    SpringBoot啟動(dòng)過(guò)程逐步分析講解

    這篇文章主要介紹了SpringBoot啟動(dòng)過(guò)程的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2023-01-01
  • Netty源碼分析NioEventLoop初始化線程選擇器創(chuàng)建

    Netty源碼分析NioEventLoop初始化線程選擇器創(chuàng)建

    這篇文章主要介紹了Netty源碼分析NioEventLoop初始化線程選擇器創(chuàng)建,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-03-03
  • 解決IDEA創(chuàng)建maven項(xiàng)目時(shí)pom.xml沒有變藍(lán)的問題

    解決IDEA創(chuàng)建maven項(xiàng)目時(shí)pom.xml沒有變藍(lán)的問題

    這篇文章主要介紹了解決IDEA創(chuàng)建maven項(xiàng)目時(shí)pom.xml沒有變藍(lán)的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-08-08
  • Java編寫實(shí)現(xiàn)坦克大戰(zhàn)小游戲

    Java編寫實(shí)現(xiàn)坦克大戰(zhàn)小游戲

    這篇文章主要為大家詳細(xì)介紹了Java編寫實(shí)現(xiàn)坦克大戰(zhàn)小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01

最新評(píng)論

永安市| 甘谷县| 扎赉特旗| 普定县| 武穴市| 铅山县| 宁德市| 温泉县| 达州市| 塔河县| 遵义市| 界首市| 铜川市| 永定县| 新和县| 耒阳市| 盈江县| 定陶县| 甘洛县| 河北省| 吴桥县| SHOW| 鄢陵县| 安岳县| 始兴县| 临湘市| 宜章县| 莲花县| 康平县| 通州区| 石景山区| 西和县| 罗平县| 忻城县| 金山区| 伊吾县| 普格县| 哈尔滨市| 镇原县| 金川县| 卓资县|