【问题标题】:CompletableFuture<T> class: join() vs get()CompletableFuture<T> 类:join() 与 get()
【发布时间】:2018-01-11 10:03:39
【问题描述】:

CompletableFuture&lt;T&gt; 类的get()join() 方法有什么区别?

下面是我的代码:

List<String> process() {

    List<String> messages = Arrays.asList("Msg1", "Msg2", "Msg3", "Msg4", "Msg5", "Msg6", "Msg7", "Msg8", "Msg9",
            "Msg10", "Msg11", "Msg12");
    MessageService messageService = new MessageService();
    ExecutorService executor = Executors.newFixedThreadPool(4);

    List<String> mapResult = new ArrayList<>();

    CompletableFuture<?>[] fanoutRequestList = new CompletableFuture[messages.size()];
    int count = 0;
    for (String msg : messages) {
        CompletableFuture<?> future = CompletableFuture
                .supplyAsync(() -> messageService.sendNotification(msg), executor).exceptionally(ex -> "Error")
                .thenAccept(mapResult::add);

        fanoutRequestList[count++] = future;
    }

    try {
        CompletableFuture.allOf(fanoutRequestList).get();
      //CompletableFuture.allOf(fanoutRequestList).join();
    } catch (InterruptedException | ExecutionException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return mapResult.stream().filter(s -> !s.equalsIgnoreCase("Error")).collect(Collectors.toList());
}

这两种方法我都试过了,但我看不出结果有什么不同。

【问题讨论】:

  • get() 要求您捕获已检查的异常。当您从get() 更改为join() 时,您应该注意到不同之处,因为您会立即收到一个编译器错误,指出try 块中既没有InterruptedException 也没有ExecutionException
  • @holi-java: join() 不能被打断。
  • @Holger 是的,先生。我发现我不能打断任务。
  • 好吧get 存在,因为CompletableFuture 实现了要求它的Future 接口。 join() 很可能已经被引入,以避免在组合期货时需要在 lambda 表达式中捕获已检查的异常。在所有其他用例中,请随意使用您喜欢的任何内容。
  • 在线程上同时使用 join 或 get 作为块真的有意义吗?难道我们不能通过使用其他组合方法来创建异步函数链来使这个异步。当然,它取决于功能。但是在例如的情况下Spring 中由控制器方法调用的服务方法返回可完成的未来,根本不调用 get 或加入服务方法更有意义。是吗?

标签: java java-8 completable-future


【解决方案1】:

除了 Dawid 提供的答案之外,get 方法还有两种风格:

get()
get(Long timeout, TimeUnit timeUnit) 

第二个get将等待时间作为参数,最多等待提供的等待时间。

try {
    System.out.println(cf.get(1000, TimeUnit.MILLISECONDS));
} catch (InterruptedException | ExecutionException | TimeoutException ex) {
    ex.printStackTrace();
}

您可以参考this documentation了解更多信息。

  1. join() 定义在 CompletableFuture 中,而 get() 来自接口 Future
  2. join() 抛出未检查异常,而 get() 抛出检查异常
  3. 您可以中断 get(),然后引发 InterruptedException
  4. get() 方法允许指定最大等待时间

【讨论】:

    【解决方案2】:

    唯一的区别是方法如何抛出异常。 get()Future 接口中声明为:

    V get() throws InterruptedException, ExecutionException;
    

    这些异常都是已检查异常,这意味着它们需要在您的代码中进行处理。正如您在代码中看到的,IDE 中的自动代码生成器要求您代表您创建 try-catch 块。

    try {
      CompletableFuture.allOf(fanoutRequestList).get() 
    } catch (InterruptedException | ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    

    join() 方法不会抛出 checked 异常。

    public T join()
    

    而是抛出 unchecked CompletionException。因此,您不需要 try-catch 块,而是可以在使用讨论过的 List&lt;String&gt; process 函数时充分利用 exceptionally() 方法

    CompletableFuture<List<String>> cf = CompletableFuture
        .supplyAsync(this::process)
        .exceptionally(this::getFallbackListOfStrings) // Here you can catch e.g. {@code join}'s CompletionException
        .thenAccept(this::processFurther);
    

    您可以找到get()join() 实现here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-21
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-12
      相关资源
      最近更新 更多