gpt4 book ai didi

java - 如何转换代码以使用CompletableFuture?

转载 作者:行者123 更新时间:2023-12-01 06:37:38 25 4
gpt4 key购买 nike

我曾经有一个可调用的类

class SampleTask implements Callable<Double> {
@Override
public Double call() throws Exception {
return 0d;
}
}

我曾经使用ExecutorService来提交Callable。如何更改为使用CompletableFuture.supplyAsync

以下代码无法编译

SampleTask task = new SampleTask();
CompletableFuture.supplyAsync(task);

No instance of type of variable U exists so that SampleTask conforms to Supplier

最佳答案

对于您编写的可调用文件,您可以简单地使用 CompletableFuture.supplyAsync(() -> 0d); .

但是,如果您已有 Callable ,与 CompletableFuture 一起使用由于可调用对象可能会抛出已检查的异常,因此并不是那么简单。

您可以使用临时 Supplier它捕获异常并重新抛出它,包装在未经检查的异常中,例如

CompletableFuture.supplyAsync(() -> {
try { return callable.call(); }
catch(Exception e) { throw new CompletionException(e); }
})

使用特定类型CompletionException而不是 RuntimeException 的任意子类型避免得到 CompletionException包装运行时异常 包装调用 join() 时的实际异常.

不过,当将异常处理程序链接到 CompletableFuture 时,您会注意到包装。 。另外,CompletionExceptionjoin() 抛出将是在 catch 中创建的一个子句,因此包含某个后台线程的堆栈跟踪,而不是调用 join() 的线程。换句话说,该行为仍然不同于 Supplier这会引发异常。

使用稍微复杂一点的

public static <R> CompletableFuture<R> callAsync(Callable<R> callable) {
CompletableFuture<R> cf = new CompletableFuture<>();
CompletableFuture.runAsync(() -> {
try { cf.complete(callable.call()); }
catch(Throwable ex) { cf.completeExceptionally(ex); }
});
return cf;
}

你会得到一个CompletableFuture其行为与 supplyAsync 完全相同,没有额外的包装异常类型,即如果您使用

callAsync(task).exceptionally(t -> {
t.printStackTrace();
return 42.0;
})

t将是 Callable 抛出的确切异常,如果有的话,即使它是一个受检查的异常。另外callAsync(task).join()会产生 CompletionException带有 join() 调用者的堆栈跟踪直接包装Callable抛出的异常在特殊情况下,与 Supplier 完全相同或类似 runAsync .

关于java - 如何转换代码以使用CompletableFuture?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43764036/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com