java - CompletableFuture.allOf 使用哪个执行器?

标签 java parallel-processing java-8 completable-future

假设我们有两个执行器,1 和 2。

我们可以配置在做的时候使用哪个executor

CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(()-> {return 1;}, executor1) //executor1
CompletableFuture<Integer> cf2 = CompletableFuture.supplyAsync(()-> {return 2;}, executor1) //executor1
CompletableFuture<Integer> cf3 = CompletableFuture.supplyAsync(()-> {return 3;}, executor2) //executor2

但哪个线程执行器使用 CompletableFuture 静态方法 allOf?

CompletableFuture.allOf(cf1, cf2, cf3)

谢谢!

最佳答案

The answer of Ivan Gammel不准确。

确实没有与 allOf() 返回的 CompletableFuture 关联的执行器,事实上,从来没有与任何 CompletableFuture 关联的执行器

一个任务与一个执行器相关联,因为它在其中运行,但关联是相反的:执行器有一个要执行的任务列表。

任务也可以与 CompletableFuture 相关联,它会在任务完成时完成。 CompletableFuture 本身不保留对用于其创建的任务或执行程序的引用。但是,它可能会保留对依赖阶段中使用的任务和可选执行程序的引用。

allOf() 返回的CompletableFuture 将由一个任务完成,它是原始CompletableFuture 的依赖阶段。在您的示例中,此任务可以通过以下方式执行:

  • executor1,如果第三个任务先完成;
  • executor2,如果前两个任务在第三个任务之前完成;或
  • 原始线程,如果所有任务在您调用 allOf() 之前完成。

这可以通过向 allOf() 调用添加依赖的 thenRun() 阶段来看出:

public class CompletableFutureAllOfCompletion {
    private ExecutorService executor1 = Executors.newFixedThreadPool(2);
    private ExecutorService executor2 = Executors.newFixedThreadPool(2);
    private Random random = new Random();

    public static void main(String[] args) {
        new CompletableFutureAllOfCompletion().run();
    }

    public void run() {
        CompletableFuture<Integer> cf1 = supplyAsync(this::randomSleepAndReturn, executor1);
        CompletableFuture<Integer> cf2 = supplyAsync(this::randomSleepAndReturn, executor1);
        CompletableFuture<Integer> cf3 = supplyAsync(this::randomSleepAndReturn, executor2);
        randomSleepAndReturn();
        CompletableFuture.allOf(cf1, cf2, cf3)
                .thenRun(() -> System.out.println("allOf() commpleted on "
                        + Thread.currentThread().getName()));

        executor1.shutdown();
        executor2.shutdown();
    }

    public int randomSleepAndReturn() {
        try {
            final long millis = random.nextInt(1000);
            System.out.println(
                    Thread.currentThread().getName() + " waiting for " + millis);
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 0;
    }
}

一些可能的输出:

在第一个执行者上完成(第三个任务先完成):

pool-1-thread-1 waiting for 937
pool-1-thread-2 waiting for 631
main waiting for 776
pool-2-thread-1 waiting for 615
allOf() commpleted on pool-1-thread-1

在第二个执行者上完成(第一个和第二个任务在第三个之前完成):

pool-1-thread-1 waiting for 308
pool-1-thread-2 waiting for 788
main waiting for 389
pool-2-thread-1 waiting for 863
allOf() commpleted on pool-2-thread-1

在主线程上完成(所有任务在 allOf().thenRun() 之前完成):

pool-1-thread-1 waiting for 168
pool-1-thread-2 waiting for 292
main waiting for 941
pool-2-thread-1 waiting for 188
allOf() commpleted on main

如何控制在allOf()(或anyOf())之后使用的执行器

由于无法保证将使用哪个执行器,因此调用其中一种方法后应调用 *Async(, executor) 来控制将使用哪个执行器。

如果您需要返回其中一个调用的结果 CompletableFuture,只需在返回之前添加一个 thenApplyAsync(i -> i, executor)

关于java - CompletableFuture.allOf 使用哪个执行器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49959858/

相关文章:

java - 在 Java 应用程序中使用文件关联

java - 修改 JSON 结构中的所有字符串基元

c - 如何使用 Pthreads 并行化我的 n 皇后拼图?

java - Spliterator 什么时候应该停止 split ?

java - 适用于 Java 的 Google-API 日历提要

java - 如何在 map reduce 程序中解析 PDF 文件?

Haskell 推测并行执行

Java减少列表到回退链

java - java 8 中新颖的加糖功能?

java - 如何在不冒 StackOverflowError 风险的情况下使用 CompletableFuture?