Java的Thread线程对象对异常捕获的处理策略

2024-09-18 13:45:08 浏览数 (3)

Java世界里线程无处不在,如果线程抛出了异常,是如何处理的呢?

线程对异常的处理主要涉及到java.lang.Thread.UncaughtExceptionHandler

‍‍

当一个线程即将因为一个未捕获的异常而终止时,Java虚拟机会使用getUncaughtExceptionHandler查询线程的未捕获异常处理器,并调用处理器的uncaughtException方法,将线程和异常作为参数传递。如果一个线程没有明确设置其未捕获异常处理器,那么它的ThreadGroup对象就充当其未捕获异常处理器。如果ThreadGroup对象没有特别的要求来处理异常,它可以将调用转发给默认的未捕获异常处理器

1、线程明确设置其未捕获异常处理器

通过java.lang.Thread#setUncaughtExceptionHandler方法设置此线程的异常处理器,当此线程由于未捕获的异常而突然终止时调用的处理程序,示例如下:

源码:

代码语言:javascript复制
package com.renzhikeji.demo;

/**
 * @author 认知科技技术团队
 * 微信公众号:认知科技技术团队
 */
public class ThreadDemo {

    public static void main(String[] args) throws  Exception{
        ThreadGroup threadGroup = new ThreadGroup("认知科技技术团队-ThreadGroup"){
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                System.out.println("threadGroup uncaughtException:"  e.getMessage());
            }
        };

        Thread thread = Thread
                .ofPlatform()
//                .group(threadGroup)
                .name("认知科技技术团队-thread")
                .uncaughtExceptionHandler((t, e) -> {
                    System.out.println("Thread UncaughtExceptionHandler:"  e.getMessage());
                })
                .start(() -> {
                    throw new RuntimeException("test exception");
                });


        thread.join();

        System.out.println(thread.isAlive());
    }
}

执行结果:

2、线程组设置捕获异常处理器

线程组默认的异常处理会一直迭代调用其父线程组的异常处理器,直到父线程组对象为空,最终会调用Thread类全局默认的异常处理器,如果都没有,则会把异常信息输出到标准错误流

源码:java.lang.ThreadGroup#uncaughtException

我们一般重写线程组设置捕获异常处理器,示例:

代码语言:javascript复制
package com.renzhikeji.demo;

/**
 * @author 认知科技技术团队
 * 微信公众号:认知科技技术团队
 */
public class ThreadDemo {

    public static void main(String[] args) throws  Exception{
        //重写线程组异常处理
        ThreadGroup threadGroup = new ThreadGroup("认知科技技术团队-ThreadGroup"){
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                System.out.println("threadGroup uncaughtException:"  e.getMessage());
            }
        };

        Thread thread = Thread
                .ofPlatform()
                //设置线程组,使用线程组异常处理
                .group(threadGroup)
                .name("认知科技技术团队-thread")
                .start(() -> {
                    throw new RuntimeException("test exception");
                });


        thread.join();

        System.out.println(thread.isAlive());
    }
}

输出结果:

3、线程全局异常处理器

通过java.lang.Thread#setDefaultUncaughtExceptionHandler方法设置全局异常处理器,当线程由于未捕获的异常而突然终止时调用其默认处理器处理,示例如下:

代码语言:javascript复制
package com.renzhikeji.demo;

/**
 * @author 认知科技技术团队
 * 微信公众号:认知科技技术团队
 */
public class ThreadDemo {

    public static void main(String[] args) throws  Exception{

        //设置线程全局异常处理器
        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                System.out.println("Thread DefaultUncaughtExceptionHandler :"  e.getMessage());
            }
        });

        Thread thread = Thread
                .ofPlatform()
                .name("认知科技技术团队-thread")
                .start(() -> {
                    throw new RuntimeException("test exception");
                });


        thread.join();

        System.out.println(thread.isAlive());
    }
}

执行结果:

利用线程池处理业务时,有时候需要我们自己对线程异常要捕获,不能过度依赖线程处理器,否则可能导致线程退出。

0 人点赞