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

标签 java java-8

我曾经有一个可调用的类

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/

相关文章:

java-8 - CompletableFuture 具有异步运行的可变长度 Runnable 任务

java - Thymeleaf:更新表单提交表

java - 为什么我无法使用 Jackson Java 库解包和序列化 Java map ?

java - Java 8 方法引用中的混淆,用于使用 BiPredicate 实现 equals 方法

java - 使用流修改 map

java - Java中如何根据多个参数过滤列表中的数据?

java - 并行流和 forkjoinpool 在生产中使用安全吗?

Java - 计算和重命名文件名

java - Cloud SQL Postgres 找不到适用于 jdbc 的驱动程序 :postgres://google/

Java:如何检查给定时间是否介于两个时间之间?