前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >调用线程不可捕捉异步线程的异常,如何处理?

调用线程不可捕捉异步线程的异常,如何处理?

作者头像
名字是乱打的
发布2021-12-24 08:46:43
2.2K0
发布2021-12-24 08:46:43
举报
文章被收录于专栏:软件工程

一 背景描述

Java的异常在线程之间不是共享的,在线程中抛出的异常是线程自己的异常,主线程并不能捕获到。也就是说你把线程执行的代码看成另一个主函数:

代码语言:javascript
复制
public static void main(String... args) {
    //A
    new Thread(() -> {
        //B
    }).start();
}

上面A和B的运行是互相独立的,虽然说你看到B所在代码块的函数内容在main中,但是main并不能捕获到这个Runnable里函数的异常,因为它不在同一个线程之中运行,B中抛出的异常如果你不在另一个线程捕获的话,相当于就是没有异常处理,无法捕获。你这里的代码使用的是RuntimeException,你可以试试使用必须捕获的异常,编译器会报错,因为你在另一个线程中没有做任何异常处理。

那么我们如何对异步线程出现的异常进行处理呢?

一 对于单独线程的异常捕捉

在Thread中,Java提供了一个setUncaughtExceptionHandler的方法来设置线程的异常处理函数,你可以把异常处理函数传进去,当发生线程的未捕获异常的时候,由JVM来回调执行。 例子如下:

代码语言:javascript
复制
1.写个异常,int肯定格式化转换失败抛 java.lang.NumberFormatException:异常

public class ThreadExceptionRun implements Runnable {


    @Override
    public void run() {
        int i = Integer.parseInt("uncaughtException");
        System.out.println(i);
    }
}
代码语言:javascript
复制
2.写个异常处理器,实现Thread.UncaughtExceptionHandler重写uncaughtException方法

public class ThreadException implements Thread.UncaughtExceptionHandler {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        System.out.println("处理异常信息");
    }
}
代码语言:javascript
复制
3.使用

public class ThreadExceptionMain {
    public static void main(String[] args) {
        Thread thread  = new Thread(new ThreadExceptionRun());
        thread.setUncaughtExceptionHandler(new ThreadException());
        thread.start();
    }
}

二 对于线程池如何进行异步线程异常捕捉?

下面给线程池对于不可捕捉异常也提供了多种方式去处理:

1. run方法里面try/catch所有处理逻辑
代码语言:javascript
复制
public void run() {
try {
    //处理逻辑
   } catch(Exeception e) {
      //打印日志
    }
}

这是一种简单而且不易出错的线程池异常处理方式,推荐使用

2.重写ThreadPoolExecutor.afterExecute方法

前面分析过,线程池的线程在执行结束前肯定调用afterExecute方法,所有只需要重写该方法即可。

代码语言:javascript
复制
public class MyThreadPool extends ThreadPoolExecutor {
    public MyThreadPool(int corePoolSize, int maximumPoolSize,
                        long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    @Override
    public void afterExecute(Runnable r, Throwable t) {
        if(t != null) {
            System.out.println("打印异常日志:" + t);
        }
    }
}
3. 使用submit执行任务

我们知道在使用submit执行任务,该方法将返回一个Future对象不仅仅是任务的执行结果,异常也会被封装到Future对象中,通过get()方法获取。

关于这块详情可以看 https://blog.csdn.net/LJJZJ/article/details/102905926

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/9/8 下午,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一 背景描述
    • 一 对于单独线程的异常捕捉
      • 1. run方法里面try/catch所有处理逻辑
      • 2.重写ThreadPoolExecutor.afterExecute方法
      • 3. 使用submit执行任务
  • 二 对于线程池如何进行异步线程异常捕捉?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档