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

Springboot線程池異常處理的實現(xiàn)示例

 更新時間:2025年05月16日 10:56:47   作者:sjsjsbbsbsn  
在使用線程池時,異常處理可能會被忽略,從而導(dǎo)致潛在的程序問題甚至崩潰,本文主要介紹了Springboot線程池異常處理的實現(xiàn)示例,感興趣的可以了解一下

在 Java 多線程編程中,線程池(ThreadPoolExecutor)是一個常用的工具,用于管理線程的生命周期并提升應(yīng)用程序的性能。然而,在使用線程池時,異常處理可能會被忽略,從而導(dǎo)致潛在的程序問題甚至崩潰。如果任務(wù)出現(xiàn)了異常,會發(fā)生什么呢?該怎么處理呢?怎么獲取到異常信息來解決異常?想要知道如何解決,就需要了解了解線程池提交任務(wù)的兩個方法executesubmit

一.execute與submit

package demo1;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Test2 {
    public static void main(String[] args) {
        //只有一個線程的線程池
        ExecutorService threadPool = Executors.newFixedThreadPool(1);
        threadPool.execute(()->{
            System.out.println("Execute: Current thread is " + Thread.currentThread().getName());
            method_1();
        });
        Future<?> submit = threadPool.submit(() -> {
            System.out.println("Execute: Current thread is " + Thread.currentThread().getName());
            method_1();
        });
        
        Future<?> submit2 = threadPool.submit(() -> {
            System.out.println("Execute: Current thread is " + Thread.currentThread().getName());
            method_1();
        });
    }

    public static String method_1(){
        System.out.println("starting.....");
        int i = 1/0;
        System.out.println("ending.....");
        return "ok";
    }
}

這里我executesubmit 分別執(zhí)行兩個有異常的任務(wù),同時打印了當前線程,以下是運行結(jié)果

在這里插入圖片描述

可見execute方法在遇到異常之后會拋出異常,并且線程池中的線程終止

submit方法遇到異常不會拋出異常

特性executesubmit
方法定義void execute(Runnable command)Future<?> submit(Runnable task)Future<T> submit(Callable<T> task)
返回值無返回值,不關(guān)心任務(wù)的執(zhí)行結(jié)果返回 Future 對象,可用于獲取任務(wù)結(jié)果或狀態(tài)
支持任務(wù)類型僅支持 Runnable支持 Runnable 和 Callable
異常處理任務(wù)拋出的異常不會被捕獲,直接傳播到線程池的工作線程任務(wù)拋出的異常會被封裝在 Future 中,需通過 Future.get() 獲取
使用場景適用于無需獲取任務(wù)結(jié)果的場景適用于需要獲取任務(wù)執(zhí)行結(jié)果或捕獲異常的場景
示例threadPool.execute(() -> method_1());Future<?> future = threadPool.submit(() -> method_1());
任務(wù)執(zhí)行方式直接提交給線程池執(zhí)行包裝為 FutureTask 后交由線程池執(zhí)行
線程池依賴線程池的 execute 方法是基礎(chǔ)實現(xiàn)submit 方法內(nèi)部調(diào)用 execute 執(zhí)行任務(wù)
異常傳播位置通過默認的 UncaughtExceptionHandler 處理通過 Future.get() 拋出異常

二.如何處理異常

2.1使用try-catch

這里不多贅述,這是最簡單明了的方法,直接用try-catch捕獲就行

2.2 使用 ThreadPoolExecutor 的 afterExecute 方法

ThreadPoolExecutor 提供了一個 afterExecute 鉤子方法,可以在任務(wù)完成后檢查是否有異常。
通過覆蓋此方法,可以捕獲所有任務(wù)中未被捕獲的異常。

package demo1;

import java.io.IOException;
import java.util.concurrent.*;

public class Test3 {
    public static void main(String[] args) {
        ExecutorService threadPool = new /**
         * @author 方
         */
        ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>()) {
            @Override
            protected void afterExecute(Runnable r, Throwable t) {
                super.afterExecute(r, t);
                if (t != null) {
                    System.out.println("Task threw an exception: " + t.getMessage());
                }
                // 針對 Future 的異常處理
                if (r instanceof Future<?>) {
                    try {
                        ((Future<?>) r).get(); // 調(diào)用 get 檢查任務(wù)是否拋出異常
                    } catch (Exception e) {
                        System.out.println("Exception in Future: " + e.getCause());
                    }
                }
            }
        };

        threadPool.execute(() -> {
            System.out.println("Execute: Current thread is " + Thread.currentThread().getName());
            throw new RuntimeException("Test1 exception in execute");
        });
        threadPool.submit(() -> {
            System.out.println("Execute: Current thread is " + Thread.currentThread().getName());
            throw new RuntimeException("Test2 exception in submit");
        });
        threadPool.submit(() -> {
            System.out.println("Execute: Current thread is " + Thread.currentThread().getName());
            throw new RuntimeException("Test3 exception in submit");
        });
        threadPool.shutdown();

    }
}

運行結(jié)果:

在這里插入圖片描述

可見execute方法在遇到異常之后會拋出異常,并且線程池中的線程終止,submit沒有拋出異常

但是他們兩個**都記錄了異常信息**

2.3設(shè)置 UncaughtExceptionHandler

package demo1;

import java.io.IOException;
import java.util.concurrent.*;

public class Test3 {
    public static void main(String[] args) {
        //1.實現(xiàn)一個自己的線程池工廠
        ThreadFactory factory = (Runnable r) -> {
            //創(chuàng)建一個線程
            Thread t = new Thread(r);
            //給創(chuàng)建的線程設(shè)置UncaughtExceptionHandler對象 里面實現(xiàn)異常的默認邏輯
            t.setDefaultUncaughtExceptionHandler((Thread thread1, Throwable e) -> {
                //出現(xiàn)異常
                if (e != null){
                    System.out.println(Thread.currentThread().getName()+e.getMessage());
                    e.printStackTrace();
                }
            });
            return t;
        };

        //2.創(chuàng)建一個自己定義的線程池,使用自己定義的線程工廠
        ExecutorService threadPool = new ThreadPoolExecutor(
                1,
                1,
                0,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue(10),
                factory);

        threadPool.execute(() -> {
            System.out.println("Execute: Current thread is " + Thread.currentThread().getName());
            throw new RuntimeException("Test1 exception in execute");
        });
        threadPool.submit(() -> {
            System.out.println("Execute: Current thread is " + Thread.currentThread().getName());
            throw new RuntimeException("Test2 exception in submit");
        });
        threadPool.submit(() -> {
            System.out.println("Execute: Current thread is " + Thread.currentThread().getName());
            throw new RuntimeException("Test3 exception in submit");
        });
        threadPool.shutdown();

    }
}

運行結(jié)果:

在這里插入圖片描述

可見execute方法在遇到異常之后會拋出異常,并且線程池中的線程終止,submit沒有拋出異常

三.Springboot中的線程池異常處理

   @Bean(MALLCHAT_EXECUTOR)
    @Primary
    public ThreadPoolTaskExecutor mallchatExecutor() {
        //spring的線程池
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //線程池優(yōu)雅停機的關(guān)鍵
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(200);
        executor.setThreadNamePrefix("mallchat-executor-");
        //拒絕策略->滿了調(diào)用線程執(zhí)行,認為重要任務(wù)
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //自己就是一個線程工程
        executor.setThreadFactory(new MyThreadFactory(executor));
        executor.initialize();
        return executor;
    }
package org.fth.mallchat.common.common.thread;

import lombok.AllArgsConstructor;

import java.util.concurrent.ThreadFactory;

/**
 * @author 方
 */
@AllArgsConstructor
public class MyThreadFactory implements ThreadFactory {

    private static final MyUncaughtExceptionHandler MyUncaughtExceptionHandler = new MyUncaughtExceptionHandler();
    private ThreadFactory original;

    @Override
    public Thread newThread(Runnable r) {
        //執(zhí)行Spring線程自己的創(chuàng)建邏輯
        Thread thread = original.newThread(r);
        //我們自己額外的邏輯
        thread.setUncaughtExceptionHandler(MyUncaughtExceptionHandler);
        return thread;
    }
}

package org.fth.mallchat.common.common.thread;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author 方
 */
public class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
    private static final Logger log = LoggerFactory.getLogger(MyUncaughtExceptionHandler.class);

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        log.error("Exception in thread",e);
    }
}

1. 線程池配置 (ThreadPoolTaskExecutor)

在 Spring Boot 中,ThreadPoolTaskExecutor 用于管理線程池的執(zhí)行,允許我們設(shè)置線程池的核心大小、最大線程數(shù)、隊列容量等。通過這種配置,我們可以控制線程池的資源使用情況,確保任務(wù)的執(zhí)行效率與可靠性。在你的代碼中,線程池的配置包括:

  • corePoolSize 和 maxPoolSize:指定線程池的最小和最大線程數(shù)。這里設(shè)置為 10,意味著線程池最多同時運行 10 個線程。
  • queueCapacity:指定任務(wù)隊列的容量。任務(wù)超過這個容量會被拒絕執(zhí)行,進入拒絕策略處理。
  • setRejectedExecutionHandler:設(shè)置任務(wù)隊列滿時的拒絕策略。在這個配置中,使用 CallerRunsPolicy,意味著如果隊列已滿,任務(wù)會直接在調(diào)用線程中執(zhí)行,而不是拋出異常。
  • setWaitForTasksToCompleteOnShutdown(true):設(shè)置線程池在關(guān)閉時等待所有任務(wù)完成再退出,確保優(yōu)雅停機。

2. 自定義線程工廠 (ThreadFactory)

通過 ThreadFactory,你可以自定義線程的創(chuàng)建過程。在你的代碼中,你為每個線程設(shè)置了一個異常處理器。這意味著,如果線程內(nèi)發(fā)生未捕獲的異常,這些異常會被專門的異常處理器捕獲并記錄,而不是導(dǎo)致線程崩潰或丟失異常信息。

  • 自定義異常處理器:Thread.setDefaultUncaughtExceptionHandler 會設(shè)置線程的默認異常處理器,確保在任何線程中出現(xiàn)未捕獲的異常時,異常都能被記錄。這個處理器的作用是將異常信息輸出到日志中,避免錯誤被忽略或?qū)е戮€程不可控。

3. 線程銷毀與異常

線程池的行為與異常處理相關(guān):

  • 如果線程發(fā)生未捕獲的異常,UncaughtExceptionHandler 會記錄異常,但不會銷毀線程。線程池中的其他線程仍然會繼續(xù)工作。
  • 線程池會自動重用空閑線程。即使某個線程發(fā)生異常,線程池仍然會創(chuàng)建新的線程來執(zhí)行其他任務(wù),只要線程池的資源沒有完全用盡。

因此,線程池不會因單個線程的異常而銷毀整個線程池,它會繼續(xù)運行,并且通過異常處理機制記錄異常,確保系統(tǒng)的穩(wěn)定性。

現(xiàn)未捕獲的異常時,異常都能被記錄。這個處理器的作用是將異常信息輸出到日志中,避免錯誤被忽略或?qū)е戮€程不可控。

不過sumbit還是必須要get才能拿到異常信息,我們還是可以通過重寫ThreadPoolExecutor 的 afterExecute 方法 不過這樣的話就有點麻煩

到此這篇關(guān)于Springboot線程池異常處理的實現(xiàn)示例的文章就介紹到這了,更多相關(guān)Springboot線程池異常處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java讀取圖片并轉(zhuǎn)化為二進制字符串的實現(xiàn)方法

    java讀取圖片并轉(zhuǎn)化為二進制字符串的實現(xiàn)方法

    這篇文章主要介紹了java讀取圖片并轉(zhuǎn)化為二進制字符串的實例代碼,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-09-09
  • Spring的Event使用及說明

    Spring的Event使用及說明

    本文介紹了Spring中的事件機制,包括事件的實現(xiàn)方式、推送、監(jiān)聽器、異步事件、事件異常處理器等,并簡要講述了Java自帶的觀察者模式和事件機制
    2026-03-03
  • java編程中字節(jié)流轉(zhuǎn)換成字符流的實現(xiàn)方法

    java編程中字節(jié)流轉(zhuǎn)換成字符流的實現(xiàn)方法

    下面小編就為大家?guī)硪黄猨ava編程中字節(jié)流轉(zhuǎn)換成字符流的實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-01-01
  • SpringBoot+TestNG單元測試的實現(xiàn)

    SpringBoot+TestNG單元測試的實現(xiàn)

    本文主要介紹了SpringBoot+TestNG單元測試的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-07-07
  • springboot聚合工程的部署與深入講解

    springboot聚合工程的部署與深入講解

    最近在寫一個商城,使用Maven聚合工程來管理,但是其中搭建環(huán)境遇見了各種的坑,下面這篇文章主要給大家介紹了關(guān)于springboot聚合工程部署的相關(guān)資料,需要的朋友可以參考下
    2021-11-11
  • Java后臺防止客戶端重復(fù)請求、提交表單實現(xiàn)原理

    Java后臺防止客戶端重復(fù)請求、提交表單實現(xiàn)原理

    這篇文章主要介紹了Java后臺防止客戶端重復(fù)請求、提交表單實現(xiàn)原理,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-12-12
  • Mybatis應(yīng)用mysql存儲過程查詢數(shù)據(jù)實例

    Mybatis應(yīng)用mysql存儲過程查詢數(shù)據(jù)實例

    下面小編就為大家分享一篇Mybatis應(yīng)用mysql存儲過程查詢數(shù)據(jù)實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12
  • Java使用Spring Batch處理大規(guī)模數(shù)據(jù)的實踐分享

    Java使用Spring Batch處理大規(guī)模數(shù)據(jù)的實踐分享

    在處理大規(guī)模數(shù)據(jù)的場景中,批處理是一個非常常見且必要的操作,Java中的Spring Batch是一個強大的框架,能夠幫助我們高效地執(zhí)行復(fù)雜的批處理任務(wù),本文將帶大家了解如何使用Spring Batch處理大規(guī)模數(shù)據(jù),并通過代碼示例展示如何實現(xiàn)高效的批處理,需要的朋友可以參考下
    2024-10-10
  • SpringMvc3+extjs4實現(xiàn)上傳與下載功能

    SpringMvc3+extjs4實現(xiàn)上傳與下載功能

    這篇文章主要為大家詳細介紹了SpringMvc3+extjs4實現(xiàn)上傳與下載功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • SpringBoot中實現(xiàn)多文件打包下載的兩種方案

    SpringBoot中實現(xiàn)多文件打包下載的兩種方案

    在Spring Boot中實現(xiàn)多文件打包下載,一般是將多個文件壓縮成一個ZIP文件再進行下載,以下是兩種典型實現(xiàn)方案以及代碼示例,需要的朋友可以參考下
    2025-09-09

最新評論

二连浩特市| 五原县| 泰来县| 武穴市| 乌鲁木齐市| 武邑县| 慈利县| 龙岩市| 临泉县| 长岛县| 洛阳市| 郸城县| 漳浦县| 玉屏| 新乡县| 资兴市| 平谷区| 柘荣县| 易门县| 建宁县| 安新县| 万年县| 大理市| 隆昌县| 嘉善县| 封开县| 高碑店市| 鄱阳县| 德阳市| 永平县| 高陵县| 宁安市| 柏乡县| 宝坻区| 文安县| 辽源市| 乌拉特前旗| 青浦区| 沁水县| 青龙| 浙江省|