父线程捕获子线程的异常方式

如果 子线程出现异常问题 如果不在父线程中进行捕获异常 该子线程也不进行异常捕获的话 则子线程一但出现异常 则此子线程就关闭了,父线程并不知情,可能认为该子线程已经正常、运行完毕了呢,所以突显出父线程捕获子线程异常状态的重要性。在普通的单线程程序中,捕获异常只需要通过try ... catch ... finally ...代码块就可以了。那么在并发情况下,比如在父线程中启动了子线程,如何在父线程中捕获子线程中的异常,从而进行相应的处理呢?为线程设置异常处理器。具体做法有一下两种:
(1)Thread.setUncaughtExceptionHandler设置当前线程的异常处理器;
(2)Thread.setDefaultUncaughtExceptionHandler为整个程序设置默认的异常处理器;
线程出现异常,如果当前线程有异常处理器(默认没有),则优先使用该线程的异常处理器,否则,如果当前线程所属的线程组存在异常处理器,则使用线程组的异常处理器;否则,使用全局默认的DefaultUncaughtExceptionHandler;如果都没有的话,子线程就会退出。

1.设置当前线程的异常处理器

package com.example.springbootstudy.test.exception;

public class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {

    public void uncaughtException(Thread t, Throwable e) {
        System.out.println("MyUncaughtExceptionHandler do something...");
        System.out.println("errorMsg:" + e.getMessage());
    }

}
package com.example.springbootstudy.test.exception;

public class ChildTask implements Runnable {

    public void run() {
        Thread.currentThread().setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
        System.out.println("do something");
        throw new RuntimeException("ChildTask异常");
    }

    public static void main(String[] args) {
        Thread t= new Thread(new ChildTask());
        t.start();
    }


}

程序运行结果如下所示:

do something
MyUncaughtExceptionHandler do something...
errorMsg:ChildTask异常

2、设置默认异常处理器

package com.example.springbootstudy.test.exception;

public class AppTest {

    public static void main(String[] args) {
        Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
        Thread t= new Thread(new ChildTask());
        t.start();
    }
}

class ChildTask2 implements Runnable {

    public void run() {
        System.out.println("do something");
        throw new RuntimeException("ChildTask异常");
    }

}

3、Future的get
使用线程池提交一个能获取到返回信息的方法,也就是ExecutorService.submit(Callable) 在submit之后可以获得一个线程执行结果的Future对象,而如果子线程中发生了异常,通过future.get()获取返回值时,可以捕获到 ExecutionException异常,从而知道子线程中发生了异常。

 1 package com.example.springbootstudy.test.exception;
 2 
 3 import java.util.concurrent.*;
 4 
 5 public class childTask2 {
 6 
 7     public static void main(String[] args) {
 8         System.out.println("main...");
 9         ExecutorService executorService = Executors.newCachedThreadPool();
10         Future<String> future = executorService.submit(new App());
11         try {
12             String s = future.get();
13         } catch (InterruptedException e) {
14             System.out.println("InterruptedException");
15         } catch (ExecutionException e) {
16             System.out.println(e.getMessage());
17         }
18     }
19 }
20 
21 
22 class App implements Callable<String> {
23 
24     @Override
25     public String call() throws Exception {
26         System.out.println("do something");
27         throw new Exception("ChildTask2异常");
28     }
29 
30 }

总结:以上是三种父线程获取子线程的异常总结。

 

posted @ 2023-06-03 18:19  郭慕荣  阅读(792)  评论(0编辑  收藏  举报