![](/img/trans.png)
[英]How to handle uncaught exceptions from CompletableFuture.runAsync
[英]Catching uncaught exceptions from CompletableFuture
我正在尝试捕获未捕获的期货异常,例如CompletableFuture.runAsync(() -> {throw new RuntimeException();});
我的目标是让这些异常在开发人员忘记处理它们时不会沉默。
get()
或join()
和 try/catch 异常不是一个选项,因为它对于代码库中的所有 future 用法都不是全局的.exceptionnaly(...)
或handle(...)
不是一种选择。 这正是我要阻止的这是我所做的(这是行不通的)
public class Main {
public static void main(String[] args) throws InterruptedException, ExecutionException {
System.setProperty("java.util.concurrent.ForkJoinPool.common.exceptionHandler", UncaughtExceptionHandler.class.getName());
CompletableFuture.runAsync(() -> {
System.out.println("async");
throw new RuntimeException();
});
System.out.println("Done");
Thread.sleep(1000);
}
static class UncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("Uncaught!");
}
}
}
它打印
Done
Async
我错过了什么?
编辑
我试过了,但还是没用
public class Main {
public static void main(String[] args) throws InterruptedException {
CompletableFuture.runAsync(() -> {
System.out.println("Async");
throw new RuntimeException();
},
new ForkJoinPool(
Runtime.getRuntime().availableProcessors(),
ForkJoinPool.defaultForkJoinWorkerThreadFactory,
(t, e) -> System.out.println("Uncaught!"), // UncaughtExceptionHandler
false));
System.out.println("Done");
Thread.sleep(1000);
}
}
ForkJoinPool 似乎忽略了它的 UncaughtExceptionHandler,甚至忽略了它的 ForkJoinWorkerThreadFactory,因为我也试图定义它
版本 1:一切正常,RunAsync 方法没有抛出异常……没有发生异常处理……
public static void main(String[] args) throws InterruptedException {
UncaughtExceptionHandler uncaughtExceptionHandler = new UncaughtExceptionHandler();
System.setProperty("java.util.concurrent.ForkJoinPool.common.exceptionHandler", UncaughtExceptionHandler.class.getName());
CompletableFuture.runAsync(() -> {
System.out.println("async");
}).exceptionally((ex) -> {
uncaughtExceptionHandler.uncaughtException(Thread.currentThread(), ex);
return null;
});
System.out.println("Done");
Thread.sleep(1000);
}
static class UncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
public UncaughtExceptionHandler() { }
public void uncaughtException(Thread t, Throwable e) {
System.out.println("Uncaught!");
}
}
Output:
async
Done
Process finished with exit code 0
版本 2:由runAsync()
抛出异常,异常处理程序执行其操作。
public static void main(String[] args) throws InterruptedException {
UncaughtExceptionHandler uncaughtExceptionHandler = new UncaughtExceptionHandler();
System.setProperty("java.util.concurrent.ForkJoinPool.common.exceptionHandler", UncaughtExceptionHandler.class.getName());
CompletableFuture.runAsync(() -> {
throw new RuntimeException("Something went Wrong");
}).exceptionally((ex) -> {
uncaughtExceptionHandler.uncaughtException(Thread.currentThread(), ex);
return null;
});
System.out.println("Done");
Thread.sleep(1000);
}
static class UncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
public UncaughtExceptionHandler() { }
public void uncaughtException(Thread t, Throwable e) {
System.out.println("Uncaught!");
}
}
Output:
Uncaught!
Done
Process finished with exit code 0
异常处理的两种方式:
.exceptionally(ex -> { your_code })
- 让你有机会从原始 Future 产生的错误中恢复。 您可以在此处记录异常并返回默认值。 .handle((result, ex) -> { your_code })
- 无论是否发生异常都会被调用。 也可以用来处理异常
您错过了一个事实,即 CompletableFuture 在后台执行其任务(使用执行器)并处理其任务抛出的任何异常,以便从isCompletedExceptionally等方法报告任务的状态,因此没有未捕获的异常。
异常可以通过调用 CompletableFuture 的get()方法传播:
CompletableFuture<?> future =
CompletableFuture.runAsync(() -> {
System.out.println("async");
throw new RuntimeException();
});
future.get();
System.out.println("Done");
更新:
由于您不想等待异常,因此可以使用exceptionally或exceptionallyAsync来响应任务抛出的任何异常:
CompletableFuture<?> future =
CompletableFuture.runAsync(() -> {
System.out.println("async");
throw new RuntimeException();
});
future.exceptionally(e -> {
System.out.println("Uncaught!");
return null;
});
System.out.println("Done");
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.