当前位置: 首页 > 知识库问答 >
问题:

CompletableFuture handle和CompleteExceptionly不能一起工作?

梁丘远航
2023-03-14

当异常发生在CompletableFuture中时,我试图设置一个默认值,我通过如下方法使其工作:

private static void testHandle() {
    String name = null;
    CompletableFuture<String> completableFuture
            = CompletableFuture.supplyAsync(() -> {
        if (name == null) {
            throw new RuntimeException("Computation error!");
        }
        return "Hello, " + name;
    }).handle((s, t) -> s != null ? s : "Hello, Stranger!" + t.toString());
    out.println(completableFuture.join());
}

但是,当我试图在不好的事情发生时异常地使用complete来停止CompletableFuture,并按如下方式跟踪异常时,我无法像刚才那样捕捉到异常。

private static void testCompleteExceptionally() {
    String name = "Hearen";
    CompletableFuture<String> completableFuture
            = CompletableFuture.supplyAsync(() -> {
        delay(500L);
        if (name == null) {
            throw new RuntimeException("Computation error!");
        }
        return "Hello, " + name;
    }).handle((s, t) -> {
        try {
            throw t.getCause(); 
        } catch (Throwable e) {
            out.println(e.toString()); // I was hoping to record the custom exceptions here;
        }
        return s != null ? s : "Hello, Stranger!" + t.toString();
    });

    if (name != null) {
        completableFuture.completeExceptionally(new RuntimeException("Calculation failed!")); // when bad things happen, I try to complete it by exception;
    }
    out.println(completableFuture.join());

}

更新日期2018-06-09谢谢您的帮助,@Daniele

private static void testCompleteExceptionally() {
    String name = "Hearen";
    CompletableFuture<String> completableFuture
            = CompletableFuture.supplyAsync(() -> {
        delay(500L);
        if (name == null) {
            throw new RuntimeException("Computation error!");
        }
        return "Hello, " + name;
    });

    if (name != null) {
        completableFuture.completeExceptionally(new RuntimeException("Calculation failed!"));
    }
    out.println(completableFuture.handle((s, t) ->  s != null ? s : "Hello, Stranger!" + t.toString()).join());

}

在join()之前封闭的句柄按预期工作。但在这种情况下,返回值将为null。

基于handle API

返回一个新的CompletionStage,当此阶段正常或异常完成时,将使用此阶段的结果和异常作为提供的函数的参数来执行该阶段。


共有1个答案

越英范
2023-03-14

您正在构建一个未来,用一个句柄进行管道连接(从而获得另一个未来),然后异常地完成句柄返回的未来。

您应该异常地完成内部未来本身,而不是句柄。

这里的重点是句柄返回另一个未来;您不应该例外地完成“外部”未来,因为这样做会绕过处理行为。

低于代码;

package stackOv;

import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
import java.util.function.Supplier;

public class TestHandle {
  BiFunction<String, Throwable, String> handle2 = new BiFunction<String, Throwable, String>() {
    @Override
    public String apply(String s, Throwable t) {
      try {
        throw t.getCause(); 
      } catch (Throwable e) {
        // I was hoping to record the custom exceptions here;
        System.out.println(e.toString());
      }
      return s != null ? s : "Hello, Stranger!" + t.toString();
    }
  };

  private void testCompleteExceptionally() {
    String name = "Hearen";
    Supplier<String> supplier2 = () -> {
      delay(500L);
      if (name == null) {
        throw new RuntimeException("Computation error!");
      }
      return "Hello, " + name;
    };
    CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(supplier2);

    if (name != null) {
      // when bad things happen, I try to complete it by exception;
      completableFuture.completeExceptionally(new RuntimeException("Calculation failed!"));      
    }
    System.out.println(completableFuture.handle(handle2).join());
  }

  public static void main(String[] args) {
    TestHandle th = new TestHandle();
    th.testCompleteExceptionally();
  }

  private static void delay(long milli) {
    try { Thread.sleep(milli); } catch (InterruptedException e) {}    
  }
}
 类似资料:
  • {“时间戳”:1553613278534,“状态”:400,“错误”:“错误请求”,“消息”:“必需的字符串参数'param2'不存在”,“路径”:“/MyURL/42”} 我希望PUT的工作就像POST一样,但它似乎不是。 不幸的是,我不能将参数作为QueryParam发送,因此我应该维护相同的请求调用,因为我正在重构一个完全以这种方式工作的现有endpoint。

  • 我正在试验把杰克逊和龙目岛结合起来。这些是我的课: 这些是我添加到类spth中的JAR: > 龙目岛:https://projectlombok.org/downloads/lombok.jar(1.16.10version) 此外,Netbeans项目被配置为“保存时不编译”、“生成调试信息”、“报告不推荐使用的API”、“跟踪java依赖项”、“Activacte注释处理”和“编辑器中的Act

  • 更改单元格值后,我的不会刷新。我可以双击一个单元格并更改它的值,但是当我按OK或者我点击离开单元格时,值会重置为上一个,这不是更新表。这是我的自定义表模型的代码,我不知道如何更新数据库,因为当我改变单元格的值时,表是从一个db中取出来的。 如果您需要其他东西,例如数据库或表编辑器的代码,请告诉我;)谢谢您的帮助:) --编辑--好的,我已经实现了setValueAt方法,但是当我单击单元格时,它给

  • 更新后反序列化失败。 我将我的微服务从更新到,并将从更新为,从更新为。 JSON字符串- 班级 - 方法调用- 用于反序列化的方法 - 错误 -

  • pendingList 删除小部件实际上是将其从列表中删除。在用户取消任务后,该任务将从列表中“可视化地”删除,并调用方法,该方法调用。调用会导致FutureBuilder再次生成,但是在FutureBuilder再次生成时,调用尚未完成。因此,FutureBuilder将传递旧快照,这将导致ListView使用刚刚被取消的任务再次生成。这导致被解雇的列表者在被解雇后暂时出现,这看起来令人毛骨悚然

  • 根据它的Javadoc,将生成,其中的第一个值是subscribe和第一个next信号之间的经过时间。 以下测试不起作用 它将抛出异常: 我原以为经过的时间至少是1000ms,但结果只有11ms。