上一篇文章我们学习了在我们使用application的时候在他出现问题或者人为终止的时候,我们怎么有机会捕获异常或者人为的做一些操作,比如写一些日志,或者发送一个RESTful或者关闭释放一些资源,那么线程运行期间的异常该如何捕获呢?我们知道线程的运行逻辑单元在run方法里,run方法的签名是不允许抛出异常的,今天我们就来学习一下线程的Exception。
先来一段抛出异常的代码:
public class ThreadException {
private final static int A = 10;
private static final int B = 0;
public static void main(String[] args) {
/// 捕获线程运行期间的异常
Thread t = new Thread(() -> {
try {
Thread.sleep(1_000L);
int result = A / B;
System.out.println("result = " + result);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t.start();
}
}
运行效果如下:
我们改造一下我们的代码,Thread对象提供了setUncaughtExceptionHandler
方法用来获取线程中产生的异常。而且建议使用该方法为线程设置异常捕获方法:
t.setUncaughtExceptionHandler((thread, e) -> {
System.out.println(e);
System.out.println(thread.getName());
System.out.println(thread.getThreadGroup().getName());
System.out.println(thread.getThreadGroup().getParent().getName());
});
运行效果如下:
可以看到异常的详细堆栈信息已经打印出来了,下面做个实验来输出一下,先建几个类分别进行调用,如下:
public class ThreadException {
public static void main(String[] args) {
// stack trace
new Test1().test();
}
}
public class Test1 {
private Test2 test2 = new Test2();
public void test() {
test2.test();
}
}
public class Test2 {
public void test() {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
Stream.of(stackTrace)
.filter(e -> !e.isNativeMethod())
.forEach(e ->
Optional.of(e.getClassName() + "." + e.getMethodName() + ":" + e.getLineNumber())
.ifPresent(System.out::println)
);
}
}
运行效果如下:
这个在后续使用中有补充再继续补充,后面开始学习ThreadGroupApI的学习,然后实现一个线程池,java并发编程的基础就码一遍了。
原文:https://www.cnblogs.com/stormsquirrel/p/13695833.html