我正试图捕获像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似乎忽略了它的UncaughtException处理程序,甚至忽略了ForkJoinWorkerThreadFactory,因为我也试图定义
Version1:一切正常,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在后台执行其任务(使用Executor(并处理其任务引发的任何异常,以便通过isCompletedExceptionally等方法报告任务的状态,因此不存在未捕获的异常。
可以通过调用CompletableFuture的get((方法来传播异常:
CompletableFuture<?> future =
CompletableFuture.runAsync(() -> {
System.out.println("async");
throw new RuntimeException();
});
future.get();
System.out.println("Done");
更新:
由于您不想等待异常,因此可以使用exceptionally或exceptionalyAsync来响应任务引发的任何异常:
CompletableFuture<?> future =
CompletableFuture.runAsync(() -> {
System.out.println("async");
throw new RuntimeException();
});
future.exceptionally(e -> {
System.out.println("Uncaught!");
return null;
});
System.out.println("Done");