如何实现线程池中异常捕获

线程出现异常

线程执行任务时,没有添加异常处理。导致任务内部发生异常时,内部错误无法被记录下来。

 

ini

代码解读

复制代码

Thread thread =new Thread(()->{ if (1 == 1) { log.error("error"); throw new RuntimeException("异常了"); } }); thread.start(); }

可以看到,异常不会打印日志,而是输出在控制台上了。那么异常去了哪里?

异常去了哪里?

正常来说,如果我们进行了异常捕获,是可以看到日志信息的。

 

php

代码解读

复制代码

Thread thread = new Thread(()->{ try{ log.info("hello"); throw new RuntimeException("运行时异常了"); }catch (Exception e){ log.error("异常发生",e); } }); thread.start();

但是如果是一个未捕获的异常,异常是抛到控制台上的,什么原因呢?

如果一个异常未被捕获,从线程中抛了出来。JVM会回调T hread 类中dispatchUncaughtException方法。

在这方法中,就是获取一个默认的异常的处理器,我们来看看这个处理器它是怎么做的?

可以看到这里,他不会记录日志信息,而是将异常抛到了控制台中,那么线上我们一般是通过日志来排查问题,所以,我们怎么将控制台的输出转变成日志输出呢?

解决方案

其实,很简单,就是给线程添加一个异常捕获处理器,以后抛了异常,就给它转成日志。这样才能及时发现问题。

首先定义一个异常处理器:

 

typescript

代码解读

复制代码

/** * 自定义异常处理器(将异常时控制台输出,装变成日志输出) */ @Slf4j public class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler { @Override public void uncaughtException(Thread t, Throwable e) { log.error("Exception Thread",e); } }

设置异常处理器

 

arduino

代码解读

复制代码

Thread thread =new Thread(()->{ if (1 == 1) { log.error("error"); throw new RuntimeException("异常了"); } }); // 设置异常处理器 thread.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler()); thread.start();

可以看到即使没有获取异常,抛出的异常,我们也记录在日志中。

线程池如何进行异常处理呢?

可以通过线程池的ThreadFactory,创建线程的工厂,创建线程的时候给线程添加异常捕获。

首先自定义线程工厂,然后就是在保持原有线程工厂的能力,然后额外的配置我们自己自定义的异常处理器

 

arduino

代码解读

复制代码

/** * 自定义线程工厂(提供处理异常的能力) */ public class MyThreadFactory implements ThreadFactory { private static final MyUncaughtExceptionHandler UNCAUGHT_EXCEPTION_HANDLER = new MyUncaughtExceptionHandler(); private ThreadFactory originalThreadFactory; public MyThreadFactory(ThreadFactory originalThreadFactory) { this.originalThreadFactory = originalThreadFactory; } @Override public Thread newThread(Runnable r) { Thread thread = originalThreadFactory.newThread(r); // 设置我们自定义的异常处理器 thread.setUncaughtExceptionHandler(UNCAUGHT_EXCEPTION_HANDLER); return thread; } }

在线程池中配置我们的线程池工厂:

这里我使用的是Spring提供的线程池。

 

scss

代码解读

复制代码

@Configuration public class ThreadPoolConfig { @Bean public ThreadPoolTaskExecutor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(10); executor.setQueueCapacity(100); executor.setThreadNamePrefix("MyExecutor-"); executor.setThreadFactory(new MyThreadFactory(executor)); executor.initialize(); return executor; } }

new MyThreadFactory() 这里为什么可以传入这个线程池类,因为Spring中这个类本身就是一个线程工厂的类。

可以从下面看到 ThreadPoolTaskExecutor 继承了 ExecutorConfigurationSupport

可以从关系图中看到是实现了 ThreadFactory 接口的

Python中的ThreadPoolExecutor是线程池的一种实现方式,它提供了方便的接口来进行并发编程。在使用ThreadPoolExecutor时,通常会遇到异常捕获的问题。 当线程池中的线程执行任务时,如果任务发生异常异常会被捕获,并通过Future对象返回给调用者。我们可以通过检查Future对象的状态来获取异常信息。Future对象是一个表示异步计算结果的对象,它可以用来检查任务是否完成、取消任务、获取任务的结果等。 在ThreadPoolExecutor中,可以通过submit方法来提交任务。这个方法返回一个Future对象,我们可以通过调用Future对象的result方法来等待任务完成并获取任务的结果。如果任务发生异常,result方法将会抛出异常,并将异常的类型和信息传递给调用者。 另外,我们还可以通过调用ThreadPoolExecutor的shutdown方法来关闭线程池。关闭线程池后,任何待处理的任务将会被取消,并且已提交但还未开始执行的任务将会被清除。我们可以通过调用Future对象的cancel方法来取消任务。 在代码中,我们可以使用try-except语句块来捕获线程任务中的异常。可以使用ThreadPoolExecutor的submit方法来提交任务,并通过返回的Future对象来获取任务的结果。在调用Future对象的result方法时,如果发生了异常,可以使用try-except语句块来捕获异常并处理异常。另外,在使用完线程池后,我们应该调用shutdown方法来关闭线程池,以释放资源。 总结起来,Python的ThreadPoolExecutor提供了异常捕获机制,我们可以通过检查返回的Future对象来获取任务执行过程中的异常信息。在使用完线程池后,我们应该及时关闭线程池,以释放资源。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值