美文网首页人生几何?
调用线程不可捕捉异步线程的异常,如何处理?

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

作者: 名字是乱打的 | 来源:发表于2021-09-08 22:20 被阅读0次

一 背景描述

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

public static void main(String... args) {
    //A
    new Thread(() -> {
        //B
    }).start();
}

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

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

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

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

1.写个异常,int肯定格式化转换失败抛 java.lang.NumberFormatException:异常

public class ThreadExceptionRun implements Runnable {


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

public class ThreadException implements Thread.UncaughtExceptionHandler {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        System.out.println("处理异常信息");
    }
}
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所有处理逻辑

public void run() {
try {
    //处理逻辑
   } catch(Exeception e) {
      //打印日志
    }
}

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

2.重写ThreadPoolExecutor.afterExecute方法

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

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

相关文章

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

    一 背景描述 Java的异常在线程之间不是共享的,在线程中抛出的异常是线程自己的异常,主线程并不能捕获到。也就是说...

  • Java 线程异常处理

    如果我们调用一个线程处理任务,但是当线程发生异常的时候我们调用线程的地方无法捕捉到异常。用例子验证:我在main中...

  • Java 子线程异常捕获

    实现UncaughtExceptionHandler主线程可以轻松发现异常,子线程却不行。线程异常处理器的调用策略...

  • 4.1、异步servlet

    同步:接收到一个请求后,tomcat 容器提供一个线程,线程调用servlet。异步:请求异步处理后tomcat ...

  • 异步执行原理简要总结

    异步http调用,线程池调用简要原理 主线程封装一个FutureTask给异步框架, 异步框架有管理类管理主线程传...

  • Android消息机制分析

    异步消息处理线程 对于普通的线程而言,执行完run()方法内的代码后线程就结束。而异步消息处理线程是指,线程启动后...

  • Java多线程: 如何捕获多线程中的异常

    你处理过多线程中异常吗?如何捕获多线程中发生的异常?捕获子线程的异常与捕获当前线程的异常一样简单吗? 除了try ...

  • Handler使用

    主要用于异步处理: 存在于线程中开启子线程:异步处理 主要接受子线程发送的数据,并用此数据配合主线程更新UI ··...

  • 实现异步转同步

    极客时间-《Java并发编程实战》学习笔记 异步方法:调用方法,在方法中启动子线程异步调用:启动子线程调用方法异步...

  • Java多线程--Future及FutureTask

    1、Future线程是异步的,所以不可能直接从别的线程中得到函数返回值。Futrue可以监视目标线程调用call的...

网友评论

    本文标题:调用线程不可捕捉异步线程的异常,如何处理?

    本文链接:https://www.haomeiwen.com/subject/sfevwltx.html