如何实现线程池中异常捕获
创作时间:
作者:
@小白创作中心
如何实现线程池中异常捕获
引用
CSDN
1.
https://m.blog.csdn.net/2401_89221445/article/details/145856231
在多线程编程中,异常处理是一个容易被忽视但又非常重要的环节。本文将详细介绍如何在Java线程池中实现异常捕获,确保异常信息能够被正确记录和处理。
线程出现异常
在多线程环境中,如果线程执行任务时没有添加异常处理,一旦任务内部发生异常,错误信息将无法被记录下来。例如:
Thread thread = new Thread(() -> {
if (1 == 1) {
log.error("error");
throw new RuntimeException("异常了");
}
});
thread.start();
可以看到,异常不会打印日志,而是输出在控制台上了。那么异常去了哪里?
异常去了哪里?
正常来说,如果我们进行了异常捕获,是可以看到日志信息的:
Thread thread = new Thread(() -> {
try {
log.info("hello");
throw new RuntimeException("运行时异常了");
} catch (Exception e) {
log.error("异常发生", e);
}
});
thread.start();
但是如果是一个未捕获的异常,异常是抛到控制台上的,什么原因呢?
如果一个异常未被捕获,从线程中抛了出来。JVM会回调Thread类中的dispatchUncaughtException方法。在这个方法中,系统会获取一个默认的异常处理器,这个处理器会将异常信息输出到控制台,而不是记录到日志中。
解决方案
要将控制台输出转换为日志输出,我们可以给线程添加一个自定义的异常处理器。具体步骤如下:
- 定义一个异常处理器:
@Slf4j
public class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread t, Throwable e) {
log.error("Exception Thread", e);
}
}
- 在创建线程时设置异常处理器:
Thread thread = new Thread(() -> {
if (1 == 1) {
log.error("error");
throw new RuntimeException("异常了");
}
});
// 设置异常处理器
thread.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
thread.start();
这样即使没有显式捕获异常,抛出的异常也会被记录在日志中。
线程池如何进行异常处理?
在使用线程池时,可以通过自定义ThreadFactory来实现异常处理。具体步骤如下:
- 自定义线程工厂:
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;
}
}
- 在线程池配置中使用自定义线程工厂:
@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;
}
}
由于ThreadPoolTaskExecutor本身就是一个线程工厂,因此可以直接将其作为参数传递给自定义线程工厂。
通过这种方式,我们可以确保线程池中的所有线程都能正确处理未捕获的异常,并将异常信息记录到日志中。
热门推荐
从致死案例看莫西沙星:广谱抗生素也有禁区
泸州专线最新收费详解,全面解析费用构成
铁路运行图调整丨泸州高铁好消息太多!一个标题放不下
2024年度最"提心吊胆"影视剧盘点
王梓:从美院到动画界的闪耀新星
动画导演必备:绘图与设计的魔法
“九天”无人机珠海首秀:喷气动力+蜂巢任务箱,引领无人机蜂群作战
中美无人机战略对比:集群战术与网络中心战的较量
“九天”无人机:全球首架具备“航空母机”功能的重型无人机
《斗罗大陆2》11月开播,李小璐演绎武魂教皇比比东
纯真到火辣:李小璐两大经典荧幕形象
小红书2024算法升级,国际用户如何玩转?
普法战争中巴黎城墙:最后的防御与屈辱见证
1940年6月22日:法国在贡比涅森林签署二战投降书
成都地铁共线区段到底咋个坐?攻略来了
糖皮质激素全面解析:从抗炎免疫到骨质疏松风险
抗炎免疫代谢三管齐下,糖皮质激素作用机制解析
洗烘一体机、风扇等四款家电,让居家生活更舒适
从金马影后到1500万粉丝网红:李小璐的逆袭之路
李小璐:用《奋斗》中的杨晓芸证明演技实力
李小璐凭《奋斗》走红:从实力派到时尚 icon 的蜕变
双滤芯前置过滤器优势凸显,或成市场主流趋势
净水器滤芯大盘点:8种主流滤芯功能详解
从水处理到汽车制造:过滤器滤芯的六大工业应用
双11健康爆品,大数据揭秘小红书的秘密
小红书健康内容爆火时间段揭秘
从CBT到睡前习惯:全方位应对噩梦指南
42岁李小璐街头偶遇,从金马影后到直播达人
李小璐:金马影后转型都市剧,用演技回应质疑
四种家用净水器对比:过滤效果与保留矿物质如何平衡