这里有一个例子展示了两种类型的异常。考虑下面的代码片段,它们展示了两种不同的异常被抛出和处理:
public static void main(String[] args) throws Exception {
try {
syncException();
} catch (RuntimeException re) {
System.out.println("-1-");
re.printStackTrace();
}
CompletableFuture<Void> f = null;
try {
f = asyncException();
} catch (RuntimeException ex) {
System.out.println("-2-" + Thread.currentThread().getName());
ex.printStackTrace();
}
try {
f.get();
} catch (Exception ex) {
System.out.println("-3-");
ex.printStackTrace();
}
}
同步异常
private static void syncException() {
throw new RuntimeException("Sync exception @" + Thread.currentThread().getName());
}
而异步异常——在不同的线程中引发,与调用代码不同:
private static CompletableFuture<Void> asyncException() {
return CompletableFuture.runAsync(() -> {
throw new RuntimeException("Async exception @" + Thread.currentThread().getName());
}, Executors.newFixedThreadPool(1));
}
现在,当执行该代码时,会产生以下堆栈跟踪:
同步异常的堆栈跟踪:
-1-
java.lang.RuntimeException: Sync exception @main
at stackoverflow.Main.syncException(Main.java:34)
at stackoverflow.Main.main(Main.java:11)
请注意,
-2-
没有被打印出来,因为该异常是异步的。请查看第三个
catch
块的堆栈跟踪,了解如何处理异步异常。请注意,引发异常的线程与打印堆栈跟踪的线程不同:
-3-
java.util.concurrent.ExecutionException: java.lang.RuntimeException: Async exception @pool-1-thread-1
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at stackoverflow.Main.main(Main.java:26)
Caused by: java.lang.RuntimeException: Async exception @pool-1-thread-1
at stackoverflow.Main.lambda$0(Main.java:39)
at java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1626)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
相比之下,异步异常可以在程序的任何执行点潜在地发生...
对此的评论是:您会注意到,在线程
pool-1-thread-1
中的代码可能会在
main
线程执行的任何时间引发异常。这可能在不同线程之间是相对的。但在这个例子中,
main
线程是主要的程序执行,我们可以说
"Async exception @ pool-1-thread-1"
异常是异步发生的。