当前位置: 首页> 财经> 访谈 > 连云港抖音优化_学交互设计网站_淘宝关键词优化怎么弄_免费网站建设模板

连云港抖音优化_学交互设计网站_淘宝关键词优化怎么弄_免费网站建设模板

时间:2025/7/9 10:53:41来源:https://blog.csdn.net/sjsjsbbsbsn/article/details/143847631 浏览次数:0次
连云港抖音优化_学交互设计网站_淘宝关键词优化怎么弄_免费网站建设模板

Springboot线程池异常处理

在 Java 多线程编程中,线程池ThreadPoolExecutor)是一个常用的工具,用于管理线程的生命周期并提升应用程序的性能。然而,在使用线程池时,异常处理可能会被忽略,从而导致潜在的程序问题甚至崩溃。如果任务出现了异常,会发生什么呢?该怎么处理呢?怎么获取到异常信息来解决异常?想要知道如何解决,就需要了解了解线程池提交任务的两个方法executesubmit

一.executesubmit

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 分别执行两个有异常的任务,同时打印了当前线程,以下是运行结果
在这里插入图片描述

可见execute方法在遇到异常之后会抛出异常,并且线程池中的线程终止

submit方法遇到异常不会抛出异常

特性executesubmit
方法定义void execute(Runnable command)Future<?> submit(Runnable task)
Future<T> submit(Callable<T> task)
返回值无返回值,不关心任务的执行结果返回 Future 对象,可用于获取任务结果或状态
支持任务类型仅支持 Runnable支持 RunnableCallable
异常处理任务抛出的异常不会被捕获,直接传播到线程池的工作线程任务抛出的异常会被封装在 Future 中,需通过 Future.get() 获取
使用场景适用于无需获取任务结果的场景适用于需要获取任务执行结果或捕获异常的场景
示例threadPool.execute(() -> method_1());Future<?> future = threadPool.submit(() -> method_1());
任务执行方式直接提交给线程池执行包装为 FutureTask 后交由线程池执行
线程池依赖线程池的 execute 方法是基础实现submit 方法内部调用 execute 执行任务
异常传播位置通过默认的 UncaughtExceptionHandler 处理通过 Future.get() 抛出异常

二.如何处理异常

2.1使用try-catch

这里不多赘述,这是最简单明了的方法,直接用try-catch捕获就行

2.2 使用 ThreadPoolExecutorafterExecute 方法

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<>()) {@Overrideprotected 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(); // 调用 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.实现一个自己的线程池工厂ThreadFactory factory = (Runnable r) -> {//创建一个线程Thread t = new Thread(r);//给创建的线程设置UncaughtExceptionHandler对象 里面实现异常的默认逻辑t.setDefaultUncaughtExceptionHandler((Thread thread1, Throwable e) -> {//出现异常if (e != null){System.out.println(Thread.currentThread().getName()+e.getMessage());e.printStackTrace();}});return t;};//2.创建一个自己定义的线程池,使用自己定义的线程工厂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)@Primarypublic ThreadPoolTaskExecutor mallchatExecutor() {//spring的线程池ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();//线程池优雅停机的关键executor.setWaitForTasksToCompleteOnShutdown(true);executor.setCorePoolSize(10);executor.setMaxPoolSize(10);executor.setQueueCapacity(200);executor.setThreadNamePrefix("mallchat-executor-");//拒绝策略->满了调用线程执行,认为重要任务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;@Overridepublic Thread newThread(Runnable r) {//执行Spring线程自己的创建逻辑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);@Overridepublic void uncaughtException(Thread t, Throwable e) {log.error("Exception in thread",e);}
}

1. 线程池配置 (ThreadPoolTaskExecutor)

在 Spring Boot 中,ThreadPoolTaskExecutor 用于管理线程池的执行,允许我们设置线程池的核心大小、最大线程数、队列容量等。通过这种配置,我们可以控制线程池的资源使用情况,确保任务的执行效率与可靠性。在你的代码中,线程池的配置包括:

  • corePoolSizemaxPoolSize:指定线程池的最小和最大线程数。这里设置为 10,意味着线程池最多同时运行 10 个线程。
  • queueCapacity:指定任务队列的容量。任务超过这个容量会被拒绝执行,进入拒绝策略处理。
  • setRejectedExecutionHandler:设置任务队列满时的拒绝策略。在这个配置中,使用 CallerRunsPolicy,意味着如果队列已满,任务会直接在调用线程中执行,而不是抛出异常。
  • setWaitForTasksToCompleteOnShutdown(true):设置线程池在关闭时等待所有任务完成再退出,确保优雅停机。

2. 自定义线程工厂 (ThreadFactory)

通过 ThreadFactory,你可以自定义线程的创建过程。在你的代码中,你为每个线程设置了一个异常处理器。这意味着,如果线程内发生未捕获的异常,这些异常会被专门的异常处理器捕获并记录,而不是导致线程崩溃或丢失异常信息。

  • 自定义异常处理器Thread.setDefaultUncaughtExceptionHandler 会设置线程的默认异常处理器,确保在任何线程中出现未捕获的异常时,异常都能被记录。这个处理器的作用是将异常信息输出到日志中,避免错误被忽略或导致线程不可控。

3. 线程销毁与异常

线程池的行为与异常处理相关:

  • 如果线程发生未捕获的异常,UncaughtExceptionHandler 会记录异常,但不会销毁线程。线程池中的其他线程仍然会继续工作。
  • 线程池会自动重用空闲线程。即使某个线程发生异常,线程池仍然会创建新的线程来执行其他任务,只要线程池的资源没有完全用尽。

因此,线程池不会因单个线程的异常而销毁整个线程池,它会继续运行,并且通过异常处理机制记录异常,确保系统的稳定性。

现未捕获的异常时,异常都能被记录。这个处理器的作用是将异常信息输出到日志中,避免错误被忽略或导致线程不可控。

3. 线程销毁与异常

线程池的行为与异常处理相关:

  • 如果线程发生未捕获的异常,UncaughtExceptionHandler 会记录异常,但不会销毁线程。线程池中的其他线程仍然会继续工作。
  • 线程池会自动重用空闲线程。即使某个线程发生异常,线程池仍然会创建新的线程来执行其他任务,只要线程池的资源没有完全用尽。

因此,线程池不会因单个线程的异常而销毁整个线程池,它会继续运行,并且通过异常处理机制记录异常,确保系统的稳定性。

不过sumbit还是必须要get才能拿到异常信息,我们还是可以通过重写ThreadPoolExecutorafterExecute 方法 不过这样的话就有点麻烦

关键字:连云港抖音优化_学交互设计网站_淘宝关键词优化怎么弄_免费网站建设模板

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: