多线程-UncaughtException

在多线程开发中,主线程能方便地捕获异常,但子线程的异常处理较为复杂。传统的try/catch方式在每个run方法中实现,不具备普适性。本文介绍了使用UncaughtExceptionHandler进行全局异常处理的方法,便于批量处理子线程异常,例如记录到日志或接入异常监控系统。同时讨论了Java异常体系、全局异常处理的原因、run方法是否能抛出异常及其对线程状态的影响,以及如何处理未处理的线程异常。

在多线程开发中,我们会面对很多的异常问题。但是,主线程的异常我们知道很方便捕获并且处理,但是对于子线程而言呢?

package Thread_.UncaughtException;

/**
 * @program:多线程和IO
 * @descripton:传统方法无法捕获子线程异常
 * @author:ZhengCheng
 * @create:2021/9/22-10:13
 **/
public class ThreadException extends Thread {
    public static void main(String[] args) {
        try {
            new ThreadException().start();
        } catch (Exception e) {
            System.out.println("I caught this Exception");
        }
    }
//    @Override
//    public void run() {
//        throw new RuntimeException();
//    }
    //解决方案1: (不推荐) 在run方法中使用trycatch捕获异常 ,提高健壮性。
    @Override
    public void run() {
        try {
            throw new RuntimeException();
        } catch (RuntimeException e) {
            System.out.println("catch success");
        }
    }
}

 测试上述代码,在主线程中,我们是无法catch到子线程抛出的异常的。故子线程的异常,我们很难使用传统方法完成。

那么有两种解决方案:

1.在run方法中加入try/catch。这样的方法可行,但是对于每一个run方法都要编写其捕获异常的处理机制,非常麻烦,不具有普适性。

2.使用UncaughtExceptionHandler

package Thread_.UncaughtException;
/**
 * @program:多线程和IO
 * @descripton:使用我自己的Handler处理异常
 * @author:ZhengCheng
 * @create:2021/9/22-10:34
 **/
public class UseMyUEH implements Runnable {
    public static void main(String[] args) {
        Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandlerDemo("我的Handler"));
        new Thread(new UseMyUEH(),"MyThread-1").start();
        new Thread(new UseMyUEH(),"MyThread-2").start();
        new Thread(new UseMyUEH(),"MyThread-3").start();
        new Thread(new UseMyUEH(),"MyThread-4").start();
    }
    //方案二 、使用UncaughtException
    // void uncaughtexception(Thread t ,Throwable e)
    @Override
    public void run() {
        throw new RuntimeException();
    }
}
package Thread_.UncaughtException;

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

/**
 * @program:多线程和IO
 * @descripton:使用UncaughtExceptionHandler接口来处理。
 * @有三种实现方式,1.全局设置2.对线程单独设置3.对线程池进行设置。
 * @author:ZhengCheng
 * @create:2021/9/22-10:27
 **/
public class UncaughtExceptionHandlerDemo implements Thread.UncaughtExceptionHandler {
    private String name ;
    public UncaughtExceptionHandlerDemo(String name) {
        this.name = name;
    }
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        Logger logger = Logger.getAnonymousLogger();
        logger.log(Level.WARNING,"线程异常"+t.getName()+"被终止了");
        System.out.println(name+"捕获了"+t.getName()+"异常:"+e);
    }
}

 通过这样的方法,我们能够合理的批量处理子线程的异常。作为一个全局处理的方式。将所有的子线程异常,在实际开发中,可以提交到日志保存,或者交给一个总的异常监控系统。

 三个小问题:

1.java的异常体系

2.如何处理全局异常?为什么要全局处理?

3.run方法是否可以抛出异常?如果抛出异常,线程的状态会怎么样?

(不能抛出异常) 因为在原生的run方法中,是没有抛出异常的。只能自己进行try/catch

如果有异常了,线程会关闭。

4.线程中如何处理某个未处理异常?

使用UncaughtExceptionHandler进行处理。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值