【第22期】观点:IT 行业加班,到底有没有价值?

【Java 多线程】Java中主线程如何捕获子线程抛出的异常

转载 2017年01月03日 15:41:07

首先明确线程代码的边界。其实很简单,Runnable接口的run方法所界定的边界就可以看作是线程代码的边界。Runnable接口中run方法原型如下:

public void run();

而所有的具体线程都实现这个方法,所以这里就明确了一点,线程代码不能抛出任何checked异常。所有的线程中的checked异常都只能被线程本身消化掉。:) 这样本身也是符合线程的设计理念的,线程本身就是被看作独立的执行片断,它应该对自己负责,所以由它来消化所有的checked异常是很正常的。
这样就回答了楼主的第一个问题:checked异常一定要在线程内部消化。

但是,线程代码中是可以抛出错误(Error)和运行级别异常(RuntimeException)的。Error俺们可以忽略,因为通常Error是应该留给vm的,而RuntimeException确是比较正常的,如果在运行过程中满足了某种条件导致线程必须中断,可以选择使用抛出运行级别异常来处理,如下:

public void run() {
if (...) throw new RuntimeException();
}

当线程代码抛出运行级别异常之后,线程会中断。:)这点java中解释得很清楚:
@see Thread
All threads that are not daemon threads have died, either by returning from the call to the run method or “by throwing an exception that propagates beyond the run method”.
但是对于invoke此线程的主线程会产生什么影响呢?主线程不受这个影响,不会处理这个RuntimeException,而且根本不能catch到这个异常。会继续执行自己的代码 :)
所以得到结论:线程方法的异常只能自己来处理。



但是,给某个thread设置一个UncaughtExceptionHandler,可以确保在该线程出现异常时能通过回调UncaughtExceptionHandler接口的public void uncaughtException(Thread t, Throwable e) 方法来处理异常,这样的好处或者说目的是可以在线程代码边界之外(Thread的run()方法之外),有一个地方能处理未捕获异常。但是要特别明确的是:虽然是在回调方法中处理异常,但这个回调方法在执行时依然还在抛出异常的这个线程中!另外还要特别说明一点:如果线程是通过线程池创建,线程异常发生时UncaughtExceptionHandler接口不一定会立即回调。代码示例如下:

package study20170103;

/**
 * Created by apple on 17/1/3.
 */
public class ThreadTest extends ThreadGroup{

    private ThreadTest(){
        super("ThreadTest");
    }


    public static void main(String[] args) {
        new Thread(new ThreadTest(),new Runnable() {//传入继承ThreadGroup的类对象
            @Override
            public void run() {
                throw new NullPointerException();//只能抛出unchecked异常
            }
        }).start();
    }

    public   void   uncaughtException(Thread   thread,   Throwable   exception)
    {
        /**
         * 当线程抛出unckecked异常时,系统会自动调用该函数,但是是在抛出异常的线程内执行
         */
        System.out.println(thread.getId());
        exception.printStackTrace();//example,   print   stack   trace
    }
}


比之上述方法,还有一种编程上的处理方式可以借鉴,即,有时候主线程的调用方可能只是想知道子线程执行过程中发生过哪些异常,而不一定会处理或是立即处理,那么发起子线程的方法可以把子线程抛出的异常实例收集起来作为一个Exception的List返回给调用方,由调用方来根据异常情况决定如何应对。不过要特别注意的是,此时子线程早以终结。

线程设计的理念:“线程的问题应该线程自己本身来解决,而不要委托到外部。”

举报

相关文章推荐

[转]Java中主线程如何捕获子线程抛出的异常

这么来看待这个问题。首先明确线程代码的边界。其实很简单,Runnable接口的run方法所界定的边界就可以看作是线程代码的边界。Runnable接口中run方法原型如下:     <<        ...

主线程捕捉线程池中线程抛出的异常

package 线程池; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; im...

程序员升职加薪指南!还缺一个“证”!

CSDN出品,立即查看!

如何捕获java线程中的逃逸的异常

由于Java线程的本质特征,当抛出异常的时候就终止了如果再进行catch,都不在一个线程里面,所以无法捕捉到异常。Java线程中,要在run()方法中把一切的异常都处理掉,可以使用try-catch块...

java中给出一个主线程如何捕获子线程异常的例子

马克-to-win:首先我们看主线程如何捕获子线程的异常 例:1.5.4-本章源码 import java.lang.Thread.UncaughtExceptionHandler; c...

java多线程中的异常处理

在java多线程程序中,所有线程都不允许抛出未捕获的checked exception,也就是说各个线程需要自己把自己的checked exception处理掉。这一点是通过java.lang.Run...

java多线程编程之捕获子线程异常示例

java多线程程序中所有线程都不允许抛出未捕获的checked exception,也就是说各个线程需要自己把自己的checked exception处理掉。 但是无法避免的是unchecked e...

handler底层是如何将消息从子线程发送到主线程

这个问题的实质是handler机制+引用的传递. 理解handler机制有很多方法,我推荐的方法是从四个关键类Handler、Message、MessageQueue、Looper的方法入手来弄清消...

怎样让多个并发的线程暂停,然后在主线程中改变标记让它们继续运行

本人刚刚对多线程进行初步学习,对多线程只是初步的了解。因为在写代码的时候遇到的了这个问题,所以就拿来说说。 两种比较笨的解决方法。 一种是在子线程中用一个while循环判断 public voi...

Java线程未捕获异常处理

Java线程未捕获异常处理        线程执行完run方法即可正常退出,如果发生了没有捕获的异常则会异常退出。大多数情况下,由于异常导致的线程退出都不是我们想要的。所以在编写的代码的时候...

Android中Toast如何在子线程中调用

Android中Toast如何在子线程中调用 在我们编写程序的时候,碰到过很多次的想要在子线程中调用Toast,这时候程序编译没有问题,当我们开始运行在手机上的时候就会出现下列出错。 ...
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)