线程的未捕获异常如何处理?

线程的未捕获异常UncaughtException应该如何处理?

为什么需要UncaughtExceptionHandler?

  • 主线程可以轻松发现异常,子线程却不行
  • 子线程异常无法用传统方法捕获
  • 不能直接捕获的后果、提高健壮性

代码演示:

/**
 * 1. 不加try catch抛出4个异常,都带线程名字
 * 2. 加了try catch,期望捕获到第一个线程的异常,线程234不应该运行,希望看到打印出Caught Exception
 * 3. 执行时发现,根本没有Caught Exception,线程234依然运行并且抛出异常
 * 4. 说明线程的异常不能用传统方法捕获
 */
public class CantCatchDirectly implements Runnable {

    public static void main(String[] args) throws InterruptedException {
        try {
            new Thread(new CantCatchDirectly(), "MyThread-1").start();
            Thread.sleep(300);
            new Thread(new CantCatchDirectly(), "MyThread-2").start();
            Thread.sleep(300);
            new Thread(new CantCatchDirectly(), "MyThread-3").start();
            Thread.sleep(300);
            new Thread(new CantCatchDirectly(), "MyThread-4").start();
        } catch (RuntimeException e) {
            System.out.println("Caught Exception.");
        }
    }

    @Override
    public void run() {
        throw new RuntimeException();
    }
}

两种解决方案

方案一(不推荐):手动在每个run方法里进行try catch

    public void run() {
        try {
            throw new RuntimeException();
        } catch (RuntimeException e) {
            System.out.println("Caught Exception.");
        }
    }

方案二(推荐):利用UncaughtExceptionHandler

  • UncaughtExceptionHandler接口
  • void uncaughtException(Thread t, Throwable e)回调方法
  • 异常处理器的调用策略
  • 实现方式
    • 给程序统一设置
    • 给每个线程单独设置
    • 给线程池设置

代码演示:实现自己的MyUncaughtExceptionHandler

public class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {

    private String name;

    public MyUncaughtExceptionHandler(String name) {
        this.name = name;
    }

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        Logger logger = Logger.getAnonymousLogger();
        logger.log(Level.WARNING, "线程异常,终止啦" + t.getName());
        System.out.println(name + "捕获了异常" + t.getName() + "异常");
    }
}

使用刚才自己写的UncaughtExceptionHandler

public class UseOwnUncaughtExceptionHandler implements Runnable {

    public static void main(String[] args) throws InterruptedException {
        Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler("捕获器1"));

        new Thread(new UseOwnUncaughtExceptionHandler(), "MyThread-1").start();
        Thread.sleep(300);
        new Thread(new UseOwnUncaughtExceptionHandler(), "MyThread-2").start();
        Thread.sleep(300);
        new Thread(new UseOwnUncaughtExceptionHandler(), "MyThread-3").start();
        Thread.sleep(300);
        new Thread(new UseOwnUncaughtExceptionHandler(), "MyThread-4").start();
    }

    @Override
    public void run() {
        throw new RuntimeException();
    }
}

打印输出:

十一月 03, 2019 10:43:23 上午 com.hd.thread.uncaughtexception.MyUncaughtExceptionHandler uncaughtException
捕获器1捕获了异常MyThread-1异常
警告: 线程异常,终止啦MyThread-1
捕获器1捕获了异常MyThread-2异常
十一月 03, 2019 10:43:23 上午 com.hd.thread.uncaughtexception.MyUncaughtExceptionHandler uncaughtException
警告: 线程异常,终止啦MyThread-2
捕获器1捕获了异常MyThread-3异常
十一月 03, 2019 10:43:23 上午 com.hd.thread.uncaughtexception.MyUncaughtExceptionHandler uncaughtException
警告: 线程异常,终止啦MyThread-3
捕获器1捕获了异常MyThread-4异常
十一月 03, 2019 10:43:24 上午 com.hd.thread.uncaughtexception.MyUncaughtExceptionHandler uncaughtException
警告: 线程异常,终止啦MyThread-4

面试问题

1.Java异常体系

网络搜索Java异常体系图。

2.如何全局处理异常?为什么要全局处理?不处理行不行?

实现UncaughtExceptionHandler接口,自定义一个全局处理器。不处理不行,不处理的话程序会抛出异常子线程中断,主线程不影响,会继续运行。

3.run方法是否可以抛出异常?如果抛出异常,线程的状态会怎么样?

run方法不能够向外抛出异常了,只能try/catch处理,如果run方法里面抛出了RuntimeException,又没有进行处理,那么程序会抛出异常,子线程中断。

4.线程中如何处理某个未处理异常?

同问题2。

发布了112 篇原创文章 · 获赞 303 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_36221788/article/details/102879984