捕获其他线程的异常UncaughtExceptionHandler

该博客探讨了Java中如何处理子线程的异常。首先,主线程无法直接捕获子线程的异常,除非设置线程的未捕获异常处理器。通过`Thread.setDefaultUncaughtExceptionHandler`或`thread.setUncaughtExceptionHandler`可以指定当线程因未捕获异常终止时的行为。示例代码展示了如何设置和使用这些处理器来捕获和打印异常信息。
摘要由CSDN通过智能技术生成

  在A线程里起了另B线程,但B线程报错了,这时想要在A线程里捕获B线程的异常是无法做的,除非在捕获B线程前先设置线程捕获器。直接来看代码:

package com.wulf.exceptionHandler;

import java.lang.Thread.UncaughtExceptionHandler;

public class ExceptionCatcher {

    public static void main(String[] args) {

        // 1、新线程抛异常,main线程无法捕获
        try {
            new Thread() {
                @Override
                public void run() {
                    System.out.println("第一个空指针来了:");
                    throw new NullPointerException();
                }
            }.start();
        } catch (Exception e) {
            System.out.println("第一次抛出异常!");
        }

        // 2、通过线程捕获异常
        try {

            // 先休眠,等上面的线程自动结束
            Thread.sleep(1000);

            // 先设置捕获线程
            Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {

                @Override
                public void uncaughtException(Thread t, Throwable e) {
                    System.out.printf("线程:%s 抛出异常:%s\n", t.getName(), e.getClass().getName());
                    e.printStackTrace();
                }
            });

            // 新起线程抛出异常
            new Thread() {

                @Override
                public void run() {
                    System.out.println("第二个空指针来了:");
                    throw new NullPointerException();

                }
            }.start();

        } catch (

        Exception e) {
            System.out.println("第二次抛出异常!");
        }
    }
}

  运行结果:

第一个空指针来了:
Exception in thread "Thread-0" java.lang.NullPointerException
    at com.wulf.exceptionHandler.ExceptionCatcher$1.run(ExceptionCatcher.java:16)
    at java.lang.Thread.run(Thread.java:745)
第二个空指针来了:
线程:Thread-1 抛出异常:java.lang.NullPointerException
java.lang.NullPointerException
    at com.wulf.exceptionHandler.ExceptionCatcher$3.run(ExceptionCatcher.java:46)
    at java.lang.Thread.run(Thread.java:745)

  根据线程执行速度不同,新起的线程里exception和本地线程里字符串的打印顺序先后有可能不同。看下的UncaughtExceptionHandler的源码:

    /**
     * Interface for handlers invoked when a <tt>Thread</tt> abruptly
     * terminates due to an uncaught exception.
     * <p>When a thread is about to terminate due to an uncaught exception
     * the Java Virtual Machine will query the thread for its
     * <tt>UncaughtExceptionHandler</tt> using
     * {@link #getUncaughtExceptionHandler} and will invoke the handler's
     * <tt>uncaughtException</tt> method, passing the thread and the
     * exception as arguments.
     * If a thread has not had its <tt>UncaughtExceptionHandler</tt>
     * explicitly set, then its <tt>ThreadGroup</tt> object acts as its
     * <tt>UncaughtExceptionHandler</tt>. If the <tt>ThreadGroup</tt> object
     * has no
     * special requirements for dealing with the exception, it can forward
     * the invocation to the {@linkplain #getDefaultUncaughtExceptionHandler
     * default uncaught exception handler}.
     *
     * @see #setDefaultUncaughtExceptionHandler
     * @see #setUncaughtExceptionHandler
     * @see ThreadGroup#uncaughtException
     * @since 1.5
     */
    @FunctionalInterface
    public interface UncaughtExceptionHandler {
        /**
         * Method invoked when the given thread terminates due to the
         * given uncaught exception.
         * <p>Any exception thrown by this method will be ignored by the
         * Java Virtual Machine.
         * @param t the thread
         * @param e the exception
         */
        void uncaughtException(Thread t, Throwable e);
    }

  上面的注释告诉我们线程查找未捕获异常的顺序:Thread实例的setUncaughtExceptionHandler -> ThreadGroup的setUncaughtExceptionHandler -> 

Thread的静态方法Thread.setDefaultUncaughtExceptionHandler。我们把例子改一下:

public class Test {
    public static void main(String[] args) {

        // 1、新线程抛异常,main线程无法捕获
        try {
            new Thread() {
                @Override
                public void run() {
                    System.out.println("第一个空指针来了:");
                    throw new NullPointerException();
                }
            }.start();
        } catch (Exception e) {
            System.out.println("第一次抛出异常!");
        }

        // 2、通过线程捕获异常
        try {

            // 先休眠,等上面的线程自动结束
            Thread.sleep(1000);

            // 先设置捕获线程
            Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {

                @Override
                public void uncaughtException(Thread t, Throwable e) {
                    System.out.printf("[setDefaultUncaughtExceptionHandler] 线程:%s 抛出异常:%s\n", t.getName(), e.getClass().getName());
                    e.printStackTrace();
                }
            });

            // 新起线程抛出异常
            Thread thread = new Thread() {

                @Override
                public void run() {
                    System.out.println("第二个空指针来了:");
                    throw new NullPointerException();

                }
            };

            thread.setUncaughtExceptionHandler((Thread t, Throwable e) -> {
                System.out.printf("[setUncaughtExceptionHandler] 线程:%s 抛出异常:%s\n", t.getName(), e.getClass().getName());
                e.printStackTrace();
            });
            thread.start();

        } catch (

                Exception e) {
            System.out.println("第二次抛出异常!");
        }
    }
}

  运行结果:

第一个空指针来了:
Exception in thread "Thread-0" java.lang.NullPointerException
    at com.wlf.springcloudgateway.Test$1.run(Test.java:33)
第二个空指针来了:
[setDefaultUncaughtExceptionHandler] 线程:Thread-1 抛出异常:java.lang.NullPointerException
java.lang.NullPointerException
    at com.wlf.springcloudgateway.Test$3.run(Test.java:62)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值