您的位置 首页 java

并发编程 | 1.8 线程中的不可控异常 如何处理?

在任何编程语言中,提供应用中错误情景的管理机制都是非常重要的。和其他现代编程语言一样,Java 编程语言提供了基于异常的错误管理机制。当发生错误情况时,Java 将抛出异常类。除了已有的异常类,还可以自定义异常类,以便管理类中产生的错误。

Java 也提供了捕获和处理异常的机制。有一些异常必须被捕获或者通过方法上的throws声明再次抛出,这类异常被称为检查异常。而有一些异常不需要方法上的声明或捕获,这类异常被称为非检查异常。

  • 检查异常: 该异常必须在方法的throws语句中声明,或者在方法内部捕获,例如IOException或ClassNotFoundException。
  • 非检查异常: 该异常不需要声明或者捕获,例如NumberFormatException。

如果在一个线程对象的run()方法内抛出检查异常,则必须对其进行捕获处理,因为run()方法不接受throws语句。如果一个非检查异常在一个线程对象的run()方法内被抛出,则会默认将异常栈信息打印到控制台,并退出程序。

幸运的是,Java 提供了用于捕获和处理线程对象中抛出的非检查异常机制,以避免程序的结束。

本节将在案例中使用这种机制。

 /**
 * @Author wj
 * @Description 实现一个处理非检查异常的类。
 * 该类必须实现UncaughtExceptionHandler接口
 * @Date 14:20 2022/5/24
 **/public class ExceptionHandler implements Thread.UncaughtExceptionHandler {

    /**
     * @Author wj
     * @Description 用于输出异常和抛出线程信息
     * @Date 14:21 2022/5/24
     **/    @Override
    public void uncaughtException(Thread t, Throwable e) {
        System.out.printf("An exception has been captured\n");
        System.out.printf("Thread: %s\n", t.getId());
        System.out.printf("Exception: %s: %s\n",
                e.getClass().getName(), e.getMessage());
        System.out.printf("Stack Trace: \n");
        e.printStackTrace(System.out);
        System.out.printf("Thread status: %s\n", t.getState());
    }

    public static class Task implements Runnable {
        @Override
        public void run() {
            //构造异常
            int numero = Integer.parseInt("TTT");
        }
    }

    public static void main(String[] args) {
        Task task = new Task();
        Thread thread = new Thread(task);
        //为线程设置非检查异常处理器
        thread.setUncaughtExceptionHandler(new ExceptionHandler());
        thread.start();
    }
}  

结果分析

案例运行结果如下图所示。异常被抛出后,异常处理器会将其捕获,然后输出该异常及抛出线程的信息。这些信息均打印到控制台:

当线程中抛出一个异常且未捕获(必须是非检查异常)时,JVM 会检查是否通过相关方法为该线程配置了未捕获异常处理器(UncaughtExceptionHandler)。如果有,那么 JVM 将调用线程对象上相应的方法,并传递抛出的异常作为参数。

如果线程对象没有配置未捕获异常处理器,则 JVM 会在控制台中打印出异常信息栈,然后结束异常抛出线程的执行。

其他说明

Thread类中还定义了另一个用于处理未捕获异常的方法。

即静态方法setDefault- UncaughtExceptionHandler()。该方法可以为应用中所有线程对象设置默认的未捕获异常处理器。

当线程中抛出未捕获异常时,JVM 会为该异常依次查找 3 个可能的处理器。

首先,如本节所介绍的,JVM 会查找线程对象的未捕获异常处理器。如果该处理器不存在,则 JVM 将查找在 1.10 节中介绍的线程组的未捕获异常处理器。如果该处理器仍然不存在,则 JVM 将会查找默认的异常处理器。

当然,如果上述异常处理器都不存在,那么 JVM 会在控制台中打印异常信息栈,然后结束异常抛出线程的执行。

文章来源:智云一二三科技

文章标题:并发编程 | 1.8 线程中的不可控异常 如何处理?

文章地址:https://www.zhihuclub.com/183024.shtml

关于作者: 智云科技

热门文章

网站地图