5.线程异常

文章通过示例代码展示了在Java中为什么不能直接通过try-catch捕获线程异常,以及如何通过UncaughtExceptionHandler实现全局异常处理器,以此确保线程异常能被正确捕获和处理。
摘要由CSDN通过智能技术生成

1.不能用传统方法捕获线程异常

public class CannotCatchDirectly implements Runnable {
    @Override
    public void run() {
        throw new RuntimeException();
    }

    public static void main(String[] args) throws InterruptedException {
        CannotCatchDirectly cannotCatchDirectly = new CannotCatchDirectly();
        try {
            Thread thread1 = new Thread(cannotCatchDirectly, "Thread1");
            thread1.start();
            Thread.sleep(1000);
            Thread thread2 = new Thread(cannotCatchDirectly, "Thread2");
            thread2.start();
            Thread.sleep(1000);
            Thread thread3 = new Thread(cannotCatchDirectly, "Thread3");
            thread3.start();
            Thread.sleep(1000);
            Thread thread4 = new Thread(cannotCatchDirectly, "Thread4");
            thread4.start();
            Thread.sleep(1000);
        } catch (RuntimeException exception) {
            System.out.println(Thread.currentThread().getName() + "抛出异常");
        }
    }
}

程序执行结果如下所示,当Thread1抛出异常时,应当进入catch分支,并终止程序运行。但实际上没有,程序继续运行,4个子线程分别抛出异常,这说明使用try catch没有捕获到子线程异常。

Exception in thread "Thread1" java.lang.RuntimeException
	at com.leichuangkj.threads.CannotCatchDirectly.run(CannotCatchDirectly.java:6)
	at java.lang.Thread.run(Thread.java:748)
Exception in thread "Thread2" java.lang.RuntimeException
	at com.leichuangkj.threads.CannotCatchDirectly.run(CannotCatchDirectly.java:6)
	at java.lang.Thread.run(Thread.java:748)
Exception in thread "Thread3" java.lang.RuntimeException
	at com.leichuangkj.threads.CannotCatchDirectly.run(CannotCatchDirectly.java:6)
	at java.lang.Thread.run(Thread.java:748)
Exception in thread "Thread4" java.lang.RuntimeException
	at com.leichuangkj.threads.CannotCatchDirectly.run(CannotCatchDirectly.java:6)
	at java.lang.Thread.run(Thread.java:748)

2.UncaughtExceptionHandler源码分析

public class ThreadGroup implements Thread.UncaughtExceptionHandler {
	public void uncaughtException(Thread t, Throwable e) {
		//默认情况下parent是null
        if (parent != null) {
            parent.uncaughtException(t, e);
        } else {
        	//设置全局handler进行处理
            Thread.UncaughtExceptionHandler ueh = Thread.getDefaultUncaughtExceptionHandler();
            if (ueh != null) {
                ueh.uncaughtException(t, e);
            } else if (!(e instanceof ThreadDeath)) {
            	//全局handler不存在则输出异常堆栈
                System.err.print("Exception in thread \"" + t.getName() + "\" ");
                e.printStackTrace(System.err);
            }
        }
    }
}

3.全局异常处理器

public class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        System.out.println(t.getName() + "捕获异常,异常信息" + e.toString());
    }
}
public class CannotCatchDirectly implements Runnable {
    @Override
    public void run() {
        throw new RuntimeException();
    }

    public static void main(String[] args) throws InterruptedException {
        Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
        CannotCatchDirectly cannotCatchDirectly = new CannotCatchDirectly();
        Thread thread1 = new Thread(cannotCatchDirectly, "Thread1");
        thread1.start();
        Thread.sleep(1000);
        Thread thread2 = new Thread(cannotCatchDirectly, "Thread2");
        thread2.start();
        Thread.sleep(1000);
        Thread thread3 = new Thread(cannotCatchDirectly, "Thread3");
        thread3.start();
        Thread.sleep(1000);
        Thread thread4 = new Thread(cannotCatchDirectly, "Thread4");
        thread4.start();
        Thread.sleep(1000);
    }
}

程序执行结果如下所示,4个子线程抛出的异常都被捕获。

线程:Thread1捕获异常,异常信息为:java.lang.RuntimeException
线程:Thread2捕获异常,异常信息为:java.lang.RuntimeException
线程:Thread3捕获异常,异常信息为:java.lang.RuntimeException
线程:Thread4捕获异常,异常信息为:java.lang.RuntimeException
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值