码迷,mamicode.com
首页 > 编程语言 > 详细

7.线程的八大核心基础知识之未捕获异常如何处理

时间:2020-03-18 20:07:28      阅读:69      评论:0      收藏:0      [点我收藏+]

标签:一个   vat   rup   自己   runnable   default   throws   runtime   利用   

一.为什么需要UncaughtExceptionHandler

1.主线程可以轻松发现异常,子线程却不行

  • 运行下面程序发现,子线程出现异常会在控制台显示错误信息而不会终止主线程程序,程序依旧运行很难发现错误信息

public class ExceptionInChildThread implements Runnable {
    @Override
    public void run() {
        throw new RuntimeException();
    }

    public static void main(String[] args) {
        new Thread(new ExceptionInChildThread()).start();
        for (int i = 0; i < 1000; i++) {
            System.out.println(i);
        }
    }
}

2.子线程异常无法用传统方法捕获

  • 从下面程序可以看出,当第一个线程抛出异常后程序并没有结束继续,直到三个线程都抛出异常并且主程序执行完毕。对于普通异常当捕获到第一个异常后就会异常处理不在继续执行。

  • 这是由于异常发生在每一个线程的run方法中,主线程捕获不到子线程异常

public class CantCatchDirectly implements Runnable {
    @Override
    public void run() {
        throw new RuntimeException();
    }

    public static void main(String[] args) {
        try {

            new Thread(new CantCatchDirectly(), "thread1").start();
            Thread.sleep(100);
            new Thread(new CantCatchDirectly(), "thread2").start();
            Thread.sleep(100);
            new Thread(new CantCatchDirectly(), "thread3").start();

        } catch (InterruptedException e) {
            System.out.println("捕获到异常");
        }
    }
}

技术图片

3.UncaughtExceptionHandler处理会提高程序的健壮性

二.处理线程异常两种解决方案

1.方案一(不推荐):手动在每一个run方法中进行try/catch处理

2.方案二(推荐):利用UncaughtExceptionHandler接口处理异常

  • UncaughtExceptionHandler接口

  • void uncaughtException(Thread t, Throwable e);

(1)异常处理器的调用策略

  • 如果有父线程的异常处理就调用父线程的

  • 如果没有则判断用户是否自己实现异常处理器,自己实现了就调用自己实现的异常处理器,没有就默认打印堆栈信息

技术图片

 

 (2)自己实现异常处理器

实现方式:

  1. 给程序统一设置

  2. 给线程独立设置

  3. 给线程池设置

自定义异常捕获器:实现 Thread.UncaughtExceptionHandler 接口

import java.util.logging.Level;
import java.util.logging.Logger;

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(), e);
        System.out.println(name + "捕获了异常" + t.getName() + "异常" + e);
    }
}

使用自己的异常捕获器

public class UseOwnUncaughtExceptionHandler implements Runnable {
    @Override
    public void run() {
        throw new RuntimeException();
    }

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

        new Thread(new CantCatchDirectly(), "thread1").start();
        Thread.sleep(100);

        new Thread(new CantCatchDirectly(), "thread2").start();
        Thread.sleep(100);

        new Thread(new CantCatchDirectly(), "thread3").start();
    }
}

技术图片

 

7.线程的八大核心基础知识之未捕获异常如何处理

标签:一个   vat   rup   自己   runnable   default   throws   runtime   利用   

原文地址:https://www.cnblogs.com/zhihaospace/p/12519575.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!