当前位置 博文首页 > 盛夏温暖流年:Exception异常处理机制浅析

    盛夏温暖流年:Exception异常处理机制浅析

    作者:[db:作者] 时间:2021-07-13 19:05

    Java语言提供了异常处理机制,在日常编码中使用Exception的频率很高,而Error的使用频率相对较低一些,本篇博客主要针对这两种类型的异常进行分析。

    Exception 和 Error 都继承自Throwable,在 Java 中只有Throwable类型的实例才可以被抛出或者捕获,它是异常处理机制的基本组成类型。异常Exception和错误Error 的本质区别在于:异常能被程序本身处理,而错误无法处理。

    下图是三者之间的关系:
    在这里插入图片描述

    Error

    相比于Exception来说更严重,是程序不能处理的系统错误类,如内存溢出、虚拟机错误、线程死锁等。这类错误一般与硬件有关,与程序本身无关,通常由系统进行处理,程序本身无法捕获和处理。

    Exception

    表示程序可以处理的异常,可捕获和恢复。日常编程中应该尽可能处理异常,使程序恢复运行,而不应该随意终止异常。

    Exception 可以分为可检查异常(checked)和非检查型异常(unchecked)。

    可检查异常(checked)

    也称非运行时异常,java编译器强制程序员必须进行捕获处理,比如常见的IOExeption和SQLException。对于非运行时异常如果不进行捕获或者抛出声明处理,编译都不会通过。

    非检查型异常(unchecked)

    也称运行时异常(RuntimeException),比如常见的NullPointerException、IndexOutOfBoundsException。由程序员自行决定是否进行异常捕获处理或者抛出声明处理。

    Exception处理的2个基本原则

    1.尽量捕获特定异常而不是通用异常。

    如果捕获通用异常,会隐藏异常的详细信息,不利于其他程序员阅读自己的代码。所以针对已知类型的

    2.不要生吞(swallow)异常。

    生吞异常是指对异常进行捕获后,没有进行有效的处理以及输出,这样相当于忽略了当前异常,不利于发生异常后的排查和恢复。

    多线程中的异常捕获

    多线程不能按照顺序执行过程中捕获异常的方式来处理异常,直接在主线程中是捕获不到子线程中的异常的,所以需要进行特殊处理:

    自定义异常处理器,并设定到对应的线程工厂中。

    (1).定义异常处理器

    class MyExceptionHandler implements Thread.UncaughtExceptionHandler{
        //以下方法会在线程临近死亡时被调用
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            Logger.info("捕获异常:"+e);
        }
    }
    

    (2).定义使用该异常处理器的线程工厂

    class HanlderThreadFactory implements ThreadFactory{
        @Override
        public Thread newThread(Runnable r) {
             Thread t = new Thread(r);
             Logger.info("创建新线程:"+t);
            //设定线程工厂的异常处理器
            t.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
            Logger.info("异常处理器="+t.getUncaughtExceptionHandler());
            return t;
        }
    }
    

    (3).定义一个会抛出异常的线程

    class MyExceptionThread implements Runnable{
        @Override
        public void run() {
            Thread t = Thread.currentThread();
            Logger.info("异常处理器: "+t.getUncaughtExceptionHandler());
            throw new RuntimeException();
        }
    }
    

    (4).使用线程工厂创建线程池,并调用其execute方法

    public class ThreadExceptionTest{
        public static void main(String[] args){
            ExecutorService exec = Executors.newCachedThreadPool(new HanlderThreadFactory());
            //执行自定义的线程
            exec.execute(new MyExceptionThread());
        }
    }
    

    线程异常捕获参考了以下博客,表示感谢~:
    https://blog.csdn.net/sanyaoxu_2/article/details/79162953

    cs