UncaughtExceptionHandler的作用以及简单用法

UncaughtExceptionHandler

线程的run方法不能抛出任何检查型的异常,但是非检查型的异常可能会导致线程终止,在这种情况下,线程会死亡,也会导致主线程异常终止

对于可以传播的异常,在线程死亡之前,异常会传递到一个用于处理未捕获异常的处理器。前提是这个处理器必须是一个实现了Thread.UncaughtExceptionHandler接口的类

这些话是什么意思呢,继续往下看。

如下,如果我在run方法中强行抛出异常,会报错。

image-20201218225951286

所以在线程中遇到异常了,我们只能用try-catch尽可能将异常给捕获住。

image-20201218225951286

但是在每个线程的run方法里,我们不可能将每一句代码都包裹在一个大大地try-catch代码块中吧。检查型异常我们不得不用try-catch代码块包裹住,但是非检查型异常也有不少,我们不能保证非检查型异常不出错,但是将非检查型异常都使用try-catch包裹住也不恰当。

请看下面这段代码。

第一段代码:

package concurrence;

public class UncaughtExceptionHandlerTest {
  public static void main(String[] args) throws InterruptedException {
    try {
      Thread thread1 = new Thread(new MyRunnable());
      thread1.start();
    } catch (Exception ex) {
      System.out.println("Exception:" + ex.getMessage());
    }
  }
}

class MyRunnable implements Runnable {
  @Override
  public void run() {
    System.out.println(2 / 1);
    System.out.println(2 / 0);
    System.out.println(2 / 2);
  }
}

thread1的run方法中,有一个2/0的错误,这属于ArithmeticException异常,这是一个非检查型异常,因此我们就没用try-catch代码块包裹住。但是一旦代码抛出了非检查型异常,我们在其它线程里是没办法捕获的。因此,尽管我在主线程里尝试捕获非检查型异常,但是没能捕获到,最终导致程序因为异常不得不终止。
在这里插入图片描述
正常情况下,请看:

第二段代码:

package concurrence;

public class Test {
  public static void main(String[] args) {
    try {
      dividByZero();
    } catch (Exception ex) {
      System.out.println("Exception:" + ex);
    }
  }

  public static void dividByZero() {
    System.out.println(2 / 1);
    System.out.println(2 / 0);
    System.out.println(2 / 2);
  }
}

正常情况下,我们可以捕获非检查型异常,使得我们的程序不至于因为异常而终止。
在这里插入图片描述
但是现在,在多线程中,我们无法捕获run方法中的非检查型异常。那这难道就意味着我们如果不在run方法中将非检查型异常try- catch代码块将异常catch住,那么程序就会因为异常而终止吗?

当然不是,这时候就可以让UncaughtExceptionHandler闪亮登场了。

对于可以传播的异常,在线程死亡之前,异常会传递到一个用于处理未捕获异常的处理器。前提是这个处理器必须是一个实现了Thread.UncaughtExceptionHandler接口的类。

于是,我在MyUncaughtExceptionHandler类中重写了Thread.UncaughtExceptionHandler中的uncaughtException方法,在这个方法中定义了对异常的处理。然后在thread1 start之前,使用setUncaughtExceptionHandler方法对该线程进行设置。

第三段代码:

package concurrence;

public class UncaughtExceptionHandlerTest {
  public static void main(String[] args) throws InterruptedException {
    try {
      Thread thread1 = new Thread(new MyRunnable());
      thread1.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
      thread1.start();
    } catch (Exception ex) {
      System.out.println("Exception:" + ex.getMessage());
    }
  }
}

class MyRunnable implements Runnable {
  @Override
  public void run() {
    System.out.println(2 / 1);
    System.out.println(2 / 0);
    System.out.println(2 / 2);
  }
}

class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
  @Override
  public void uncaughtException(Thread t, Throwable e) {
    System.out.println(t.getName() + " " + e.getMessage());
  }
}

这样,当run方法中出现了非检查型异常以后,在threa1死亡之前,我们能在主线程中捕获住该异常,使得主程序也能正常结束了,不至于因为异常就终止了。
在这里插入图片描述

转载:https://blog.csdn.net/qq_42799615/article/details/111658473

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值