使用UncaughtExceptionHandler重启线程

先复习Java中的异常

java.lang.Throwable  顶层父类

  |– Error错误:JVM内部的严重问题,如OOM,程序员需在代码中无法处理。

  |–Exception异常:普通的问题。通过合理的处理,程序还可以回到正常执行流程。要求程序员要进行处理。

    |–RuntimeException:未检查异常(unchecked exception)。  这类异常是程序员的逻辑问题,由于程序员的疏忽导致的错误(如数组越界,空指针等)。

      Java编译器不进行强制要求处理。 也就是说,这类异常再程序中,可以进行处理,也可以不处理。 

    |–非RuntimeException:已检查异常(checked exception)、编译时异常。这类异常是由一些外部的偶然因素所引起的。Java编译器强制要求处理。也就是说,

      程序必须进行对这类异常进行处理,throw,throws或者try catch。

 

而线程Thread的的run()方法不接受抛出语句,因此对于已检查异常,我们必须进行捕获并处理,如:

    @Override
    public void run() {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(new File(""));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }

而对于未检查异常,如果在run()方法中运行出现了未检查异常,那么默认的行为是将堆栈跟踪信息写到控制台中(或者记录到错误日志文件中),然后退出程序。

Java为我们提供了一个机制,用来捕获并处理在一个线程对象中抛出的未检查异常,以避免程序终止。用UncaughtExceptionHandler来实现这种机制。

 

不使用UncaughtExceptionHandler的场景:

public class MyThread implements Runnable {

    @Override
    public void run() {
        Integer.parseInt("yangyongjie");
        System.out.println("expect");
    }

}

控制台输出:

Exception in thread "Thread-0" java.lang.NumberFormatException: For input string: "yangyongjie"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Integer.parseInt(Integer.java:492)
    at java.lang.Integer.parseInt(Integer.java:527)
    at com.yang.spbo.other.thread.MyThread.run(MyThread.java:15)
    at java.lang.Thread.run(Thread.java:745)

此时,线程立即终止,并没有执行之后的代码输出字符串“expect”。若在执行很重要的代码之前,出现了未检查异常,导致了线程终止,那么就会导致业务异常。

 

使用UncaughtExceptionHandler后:

  首先,自定义异常处理器实现UncaughtExceptionHandler接口,用来捕获和处理运行时出现的未检查异常(RuntimeException)

public class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
    /**
     * 可以自定义处理方案,如不断重试、将异常任务存入数据库等
     * @param t
     * @param e
     */
    @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());
        new Thread(new MyThread()).start();
    }
}

接着,将异常处理器添加到线程中

public class MyThread implements Runnable {

    @Override
    public void run() {
        // 异常处理器
        Thread.currentThread().setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
        Integer.parseInt("yangyongjie");
        System.out.println("expect");
    }
}

再次运行,程序能够持续执行run方法。实际上,如果线程完成了任务,那么它在退出时不会抛出任何异常,从而完成自身生命周期

An exception has been captured
Thread: 10
Exception: java.lang.NumberFormatException: For input string: "yangyongjie"
Stack Trace: 
java.lang.NumberFormatException: For input string: "yangyongjie"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Integer.parseInt(Integer.java:492)
    at java.lang.Integer.parseInt(Integer.java:527)
    at com.yang.spbo.other.thread.MyThread.run(MyThread.java:22)
    at java.lang.Thread.run(Thread.java:745)
Thread status: RUNNABLE
An exception has been captured
Thread: 12
Exception: java.lang.NumberFormatException: For input string: "yangyongjie"
Stack Trace: 
java.lang.NumberFormatException: For input string: "yangyongjie"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Integer.parseInt(Integer.java:492)
    at java.lang.Integer.parseInt(Integer.java:527)
    at com.yang.spbo.other.thread.MyThread.run(MyThread.java:22)
    at java.lang.Thread.run(Thread.java:745)
Thread status: RUNNABLE

请注意:UncaughtExceptionHandler可以在无需重启线程的条件下,将日志记录变得更加健壮,因为默认日志在线程执行失败时,不会提供足够的上下文信息。

转载于:https://www.cnblogs.com/yangyongjie/p/11035392.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值