completablefuture join vs get

Nom*_*ram 62 java java-8

CompletableFuture.get()和CompletableFuture.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());
}
Run Code Online (Sandbox Code Playgroud)

我尝试了两种方法,但结果没有差异.

谢谢

小智 69

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

V get() throws InterruptedException, ExecutionException;
Run Code Online (Sandbox Code Playgroud)

例外是检查的异常,这意味着它们需要在您的代码中处理.正如您在代码中看到的,IDE中的自动代码生成器询问是否代表您创建try-catch块.

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

join()方法不会抛出已检查的异常.

public T join()
Run Code Online (Sandbox Code Playgroud)

相反,它会抛出未经检查的 CompletionException.因此,您不需要try-catch块,而是exceptionally()在使用disscused List<String> process函数时可以完全利用方法

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

你可以在这里找到这两个get()join()实现


Pra*_*raj 22

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

\n
get()\nget(Long timeout, TimeUnit timeUnit) \n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
try {\n    System.out.println(cf.get(1000, TimeUnit.MILLISECONDS));\n} catch (InterruptedException | ExecutionException | TimeoutException ex) {\n    ex.printStackTrace();\n}\n
Run Code Online (Sandbox Code Playgroud)\n

您可以参考此文档以获取更多信息。

\n
    \n
  1. join()\xc2\xa0定义在\xc2\xa0CompletableFuture\xc2\xa0中,而\xc2\xa0get()\xc2\xa0来自接口\xc2\xa0Future
  2. \n
  3. join()\xc2\xa0抛出未检查的异常,而\xc2\xa0get()\xc2\xa0抛出检查的异常
  4. \n
  5. 您可以中断 get()\xc2\xa0 然后抛出 \xc2\xa0InterruptedException
  6. \n
  7. get() 方法允许指定最大等待时间
  8. \n
\n

  • 这是一个很好的答案。虽然最推荐使用 join,但 join 的一个限制是您无法设置超时。get 有助于克服这个限制。 (3认同)