java 多线程异常处理

ThreadGroup的异常

UncaughtExceptinoHandler

public static void main(String[] args) {
    Runnable r = new Runnable() {
        @Override
        public void run() {
            int x = 1 / 0;
        }
    };


    Thread thd = new Thread(r);
    thd.start();
}
复制代码

默认主线程创建了一个尝试除0而故意抛出ArithmeticException对象的runnable

       按照下面的方式编译清单
       javac ExceptionThread.java
       运行程序
       java ExceptionThread
你会看到类ArithmeticException的实例抛出的一条异常栈信息:

Exception in thread "Thread-0" java.lang.ArithmeticException: / by zero
            at ExceptionThread$1.run(ExceptionThread.java)
            at java.lang.Thread.run(Thread.java:745)
复制代码

一旦run()方法抛出异常,线程就会中止并被下列活动取代:

  • java虚拟机(JVM)寻找Thread.UncaughtExceptionHandler的实例,该实例有Thread的void set UncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)方法设置。当找到这个handler时,线程就会执行他的void uncaughtException(Thread t, Throwable e)方法,这里t代表了抛出异常线程所关联的Thread对象,而e代表了被抛出的异常或者错误本身--可能会抛出一个java.lang.OutOfMemoryError对象,如果uncaughtException()抛出了一个异常或错误,这个异常或者错误会被JVM忽略。
  • 假设setUncaughtExceptionHandler()未经过调用,JVM就会把控制权给线程关联的ThreadGroup对象上的uncaughtException(Thread t, Throwable e)方法。假设这个ThreadGroup没被继承且uncaughtException方法没有被重写,那么此时若其父ThreadGroup存在,uncaughtException()又会把控制权移交给其父ThreadGroup的uncaughtException()方法。否则,就检查默认的未捕获异常处理器是否已经被设置(通过Thread的static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExcetpionHandler handler)方法)。如果默认未捕获异常处理器已经被设置过,其uncaughtException方法就会被传入相同的两个参数进行调用。反之,uncaughtException()方法检查其Throwable参数是否为java.lang.ThreadDeath的实例。如果是,就没什么特别的了。否则就像清单4-1中异常消息显示的那样,一条包含了线程名称和错误栈的消息就被打印到标准错误流中,线程名称返回子该线程的getname()方法,错误栈出自Throwable栈的printStackTrace()的方法。

    清单4-2演示了Thread的setUncaughtExceptionHandler()和setDefaultcaughtExceptionHandler()方法。


         清单4-2 未捕获异常处理器示例

public class ExceptinoThread {

    public static void main(String[] args) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                int x = 1 / 0;
            }
        };


        Thread thd = new Thread(r);
        Thread.UncaughtExceptionHandler uceh;

        uceh = new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {

                System.out.println("Caught throwable" + e + "for thread" + t);
            }
        };

        thd.setUncaughtExceptionHandler(uceh);

        uceh = new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                System.out.println("Default uncaught exception handler");
                System.out.println("Caught throwable" + e + "for thread" + t);
            }
        };
        thd.setDefaultUncaughtExceptionHandler(uceh);
        thd.start();

    }
}
复制代码


     编译清单4-2(javac ExceptionThread.java),并运行最终程序(java ExceptionThread)。你应该能观测到这样的输出:

Caught throwablejava.lang.ArithmeticException: / by zerofor threadThread[Thread-0,5,main]
复制代码


     因为默认的处理器并未调用,你看不到它的输出。想要看到那样的输出,你必须注释掉thd.setUncaughtExceptionHandler(uceh);这行。如果你也注释掉了thd.setDefaultUncaughtExceptionHandler(uceh);这行,那么你就会看到原本清单4-1中的输出。

转载于:https://juejin.im/post/5b6938c8e51d45348a301c3e

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值