问题描述
我正在尝试捕获像这样的CompletableFuture.runAsync(() -> {throw new RuntimeException();});
我的目标是在开发人员忘记处理这些异常时使这些异常保持沉默。
- 调用
get()
或join()
并尝试/捕获异常不是一种选择,因为它对于代码库中将来的所有用法都不是全局的 - 出于相同的原因,不能选择添加
.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!");
}
}
输出:
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!");
}
}
输出:
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");