completablefuture加入vs获得


92

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());
}

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


9
get()要求您捕获已检查的异常。你应该注意到其中的差别,当你从改变get()join(),你会imediately得到一个编译错误说,既不InterruptedException也不ExecutionException在抛出try块。
Holger

5
@ holi-java:join()不会被打断。
Holger

@Holger是的,先生。我发现我无法中断任务。
holi-java

8
那么get存在,因为CompletableFuture实现了Future其强制要求它的接口。join()很有可能已经引入,以避免合并期货时需要在lambda表达式中捕获检查的异常。在所有其他用例中,请随意使用您喜欢的任何东西。
Holger

1
使用join或get作为线程的两个块真的有意义吗?相反,我们不能通过使用其他组合方法来创建异步函数链来使其异步的重要性。它取决于功能。但是在例如春季的服务方法被控制器方法调用返回可完成的将来的情况下,根本不调用get或join服务方法更有意义。
Shailesh Vaishampayan

Answers:


105

唯一的区别是方法如何引发异常。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()方法不会引发检查的异常。

public T join()

而是抛出未经检查的CompletionException。因此,您不需要try-catch块,而是可以exceptionally()在使用所讨论的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);

您可以在此处找到get()join()实现

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.