欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

在 Java 多線程編程中,線程池(ThreadPoolExecutor)是一個常用的工具,用于管理線程的生命周期并提升應用程序的性能。然而,在使用線程池時,異常處理可能會被忽略,從而導致潛在的程序問題甚至崩潰。如果任務出現(xiàn)了異常,會發(fā)生什么呢?該怎么處理呢?怎么獲取到異常信息來解決異常?想要知道如何解決,就需要了解了解線程池提交任務的兩個方法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í)行兩個有異常的任務,同時打印了當前線程,以下是運行結果

在這里插入圖片描述

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

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

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

二.如何處理異常

2.1使用try-catch

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

2.2 使用 ThreadPoolExecutor 的 afterExecute 方法

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

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 檢查任務是否拋出異常
                    } 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();

    }
}

運行結果:

在這里插入圖片描述

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

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

2.3設置 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)建的線程設置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();

    }
}

運行結果:

在這里插入圖片描述

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

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

   @Bean(MALLCHAT_EXECUTOR)
    @Primary
    public ThreadPoolTaskExecutor mallchatExecutor() {
        //spring的線程池
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //線程池優(yōu)雅停機的關鍵
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(200);
        executor.setThreadNamePrefix("mallchat-executor-");
        //拒絕策略->滿了調(diào)用線程執(zhí)行,認為重要任務
        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ù)、隊列容量等。通過這種配置,我們可以控制線程池的資源使用情況,確保任務的執(zhí)行效率與可靠性。在你的代碼中,線程池的配置包括:

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

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

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

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

3. 線程銷毀與異常

線程池的行為與異常處理相關:

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

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

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

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

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

相關文章

  • Java項目中classpath類路徑是什么

    Java項目中classpath類路徑是什么

    classpath指的是類路徑,也就是編譯之后的target文件夾下的WEB-INF/class文件夾,下面這篇文章主要給大家介紹了關于Java項目中classpath類路徑是什么的相關資料,需要的朋友可以參考下
    2023-02-02
  • java實現(xiàn)文件上傳下載至ftp服務器

    java實現(xiàn)文件上傳下載至ftp服務器

    這篇文章主要為大家詳細介紹了java實現(xiàn)文件上傳下載至ftp服務器的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • 基于Java將Excel科學計數(shù)法解析成數(shù)字

    基于Java將Excel科學計數(shù)法解析成數(shù)字

    這篇文章主要介紹了基于Java將Excel科學計數(shù)法解析成數(shù)字,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-09-09
  • Java VisualVM監(jiān)控遠程JVM(詳解)

    Java VisualVM監(jiān)控遠程JVM(詳解)

    下面小編就為大家?guī)硪黄狫ava VisualVM監(jiān)控遠程JVM(詳解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • 深入了解HttpClient的ResponseHandler接口

    深入了解HttpClient的ResponseHandler接口

    這篇文章主要為大家介紹了深入了解HttpClient的ResponseHandler接口,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-10-10
  • SpringBoot中如何啟動Tomcat流程

    SpringBoot中如何啟動Tomcat流程

    這篇文章主要介紹了SpringBoot中如何啟動Tomcat流程,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-05-05
  • java集合框架線程同步代碼詳解

    java集合框架線程同步代碼詳解

    這篇文章主要介紹了java集合框架線程同步代碼詳解,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12
  • Netty分布式行解碼器邏輯源碼解析

    Netty分布式行解碼器邏輯源碼解析

    這篇文章主要為大家介紹了Netty分布式行解碼器邏輯源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-03-03
  • 解決JSON.toJSONString首字母大小寫的問題

    解決JSON.toJSONString首字母大小寫的問題

    這篇文章主要介紹了解決JSON.toJSONString首字母大小寫的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • 快速理解Java設計模式中的組合模式

    快速理解Java設計模式中的組合模式

    這篇文章主要介紹了快速理解Java設計模式中的組合模式,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11

最新評論