如果 子线程出现异常问题 如果不在父线程中进行捕获异常 该子线程也不进行异常捕获的话 则子线程一但出现异常 则此子线程就关闭了 父线程 并不知情 可能认为 该子线程已经正常 运行完毕了呢 所以 突显出父线程捕获子线程异常状态的重要性
在普通的单线程程序中,捕获异常只需要通过try ... catch ... finally ...代码块就可以了。那么,在并发情况下,比如在父线程中启动了子线程,如何在父线程中捕获子线程中的异常,从而进行相应的处理呢?
为线程设置异常处理器 具体做法有一下两种:
(1)Thread.setUncaughtExceptionHandler设置当前线程的异常处理器;
(2)Thread.setDefaultUncaughtExceptionHandler为整个程序设置默认的异常处理器;
线程出现异常,如果当前线程有异常处理器(默认没有),则优先使用该线程的异常处理器,否则,如果当前线程所属的线程组存在异常处理器,则使用线程组的异常处理器;否则,使用全局默认的DefaultUncaughtExceptionHandler;如果都没有的话,子线程就会退出。
UncaughtExceptionHandler
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());
}
}
public class ChildTask implements Runnable {
public void run() {
Thread.currentThread().setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
System.out.println("do something");
throw new RuntimeException("ChildTask异常");
}
}
public class App {
public static void main(String[] args) {
Thread t= new Thread(new ChildTask());
t.start();
}
}
设置默认异常处理器
public class ChildTask implements Runnable {
public void run() { System.out.println("do something");
throw new RuntimeException("ChildTask异常");
}
}
public class App {
public static void main(String[] args) {
Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
Thread t= new Thread(new ChildTask());
t.start();
}
}
Future的get
使用线程池提交一个能获取到返回信息的方法,也就是ExecutorService.submit(Callable) 在submit之后可以获得一个线程执行结果的Future对象,而如果子线程中发生了异常,通过future.get()获取返回值时,可以捕获到 ExecutionException异常,从而知道子线程中发生了异常
public class ChildTask2 implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("do something");
throw new Exception("ChildTask2异常");
}
}
public class App {
public static void main(String[] args) {
System.out.println("mian...");
ExecutorService executorService = Executors.newCachedThreadPool();
Future<String> future = executorService.submit(new ChildTask2());
try {
String s = future.get();
} catch (InterruptedException e) {
System.out.println("InterruptedException");
} catch (ExecutionException e) {
System.out.println(e.getMessage());
}
}
}