简体   繁体   English

CompletableFuture allof(..).join() vs CompletableFuture.join()

[英]CompletableFuture allof(..).join() vs CompletableFuture.join()

I am currently using CompletableFuture supplyAsync() method for submitting some tasks to common thread pool.我目前正在使用 CompletableFuture supplyAsync() 方法将一些任务提交到公共线程池。 Here is what code snippet looks like:下面是代码片段的样子:

final List<CompletableFuture<List<Test>>> completableFutures = resolvers.stream()
        .map(resolver -> supplyAsync(() -> task.doWork()))
        .collect(toList());

CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[completableFutures.size()])).join();

final List<Test> tests = new ArrayList<>();
completableFutures.stream()
        .map(completableFuture -> completableFuture.getNow())
        .forEach(tests::addAll);

I would like to know how below differs from above code.我想知道下面的代码与上面的代码有何不同。 I removed the parent completableFuture from below code, and added join() for each of the completableFuture instead of getNow():我从下面的代码中删除了父 completableFuture,并为每个 completableFuture 添加了 join() 而不是 getNow():

final List<CompletableFuture<List<Test>>> completableFutures = resolvers.stream()
        .map(resolver -> supplyAsync(() -> task.doWork()))
        .collect(toList());

final List<Test> tests = new ArrayList<>();
completableFutures.stream()
        .map(completableFuture -> completableFuture.join())
        .forEach(tests::addAll);

I am using this in the spring service and there are issues with thread pool exhaustion.我在 spring 服务中使用它,并且存在线程池耗尽的问题。 Any pointers is deeply appreciated.任何指针都深表感谢。

First of all, .getNow() does not work, as this method requires a fall-back value as argument for the case the future is not completed yet.首先, .getNow()不起作用,因为此方法需要一个回退值作为参数,用于未来尚未完成的情况。 Since you are assuming the future to be completed here, you should also use join() .由于您假设在这里完成未来,您还应该使用join()

Then, there is no difference regarding thread exhaustion as in either case, you are waiting for the completion of all jobs before proceeding, potentially blocking the current thread.然后,线程耗尽没有区别,因为在任何一种情况下,您都在等待所有作业完成后再继续,可能会阻塞当前线程。

The only way to avoid that, is by refactoring the code to not expect a result synchronously, but rather schedule the subsequent processing action to do done, when all jobs have been completed.避免这种情况的唯一方法是重构代码以不期望同步结果,而是在所有作业完成后安排后续处理操作完成。 Then, using allOf becomes relevant:然后,使用allOf变得相关:

final List<CompletableFuture<List<Test>>> completableFutures = resolvers.stream()
    .map(resolver -> supplyAsync(() -> task.doWork()))
    .collect(toList());

CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture<?>[0]))
    .thenAccept(justVoid -> {
        // here, all jobs have been completed
        final List<Test> tests = completableFutures.stream()
            .flatMap(completableFuture -> completableFuture.join().stream())
            .collect(toList());
        // process the result here
    });

By the way, regarding the toArray method on collections, I recommended reading Arrays of Wisdom of the Ancients顺便说一句,关于集合上的toArray方法,我推荐阅读古人智慧数组……

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM