java - CompletableFuture.supplyAsync() 中 ForkJoinPool 的行为

标签 java multithreading threadpool completable-future forkjoinpool

我正在比较 CompletableFuture.supplyAsync() 在我设置自定义 ExecutorService 或我希望我的供应商由默认执行器(如果未指定)是ForkJoinPool.commonPool()

让我们看看区别:

public class MainApplication {
  public static void main(final String[] args) throws ExecutionException, InterruptedException {

    Supplier<String> action1 = () -> {
        try {
            Thread.sleep(3000);
        }finally {
            return "Done";
        }
    };
    Function<String, String> action2 = (input) -> {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            return input + "!!";
        }
    };

    final ExecutorService executorService = Executors.newFixedThreadPool(4);

    CompletableFuture.supplyAsync(action1, executorService)
                     .thenApply  (action2)
                     .thenAccept (res -> System.out.println(res));

    System.out.println("This is the end of the execution");

  }
}

在本例中,我将 executorService 传递给我的 SupplyAsync() 并打印:

This is the end of the execution

Done!!

因此主执行结束后会打印“Done”。

但是如果我使用:

CompletableFuture.supplyAsync(action1)

所以我不传递我的自定义 executorService 并且 CompletableFuture 类在底层使用 ForkJoinPool.commonPool() 那么“Done”根本不会打印:

This is the end of the execution

Process finished with exit code 0

为什么?

最佳答案

在这两种情况下,当您这样做时

CompletableFuture.supplyAsync(action1, executorService)
                     .thenApply  (action2)
                     .thenAccept (res -> System.out.println(res));

您无需等待任务完成。但随后你的程序将退出,并且常见的 fork join 池存在差异:

ForkJoinPool.commonPool()

和常规执行者服务:

final ExecutorService executorService = Executors.newFixedThreadPool(4);

..对尝试调用 System.exit(...) 等效项使用react。

这就是 doc says关于fork join common pool,需要注意的是:

However this pool and any ongoing processing are automatically terminated upon program System.exit(int). Any program that relies on asynchronous task processing to complete before program termination should invoke commonPool().awaitQuiescence, before exit.

这是指向 ExecutorService docs 的链接,您可以关注:

The shutdown() method will allow previously submitted tasks to execute before terminating

我认为这可能是您所问的差异。

关于java - CompletableFuture.supplyAsync() 中 ForkJoinPool 的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54035090/

相关文章:

java - 使用 PEM 配置 Kafka 客户端单向 SSL

multithreading - 信号量和互斥量在实现上有什么区别?

multithreading - 子进程和线程的区别

java - Java线程ID在多个线程池中是否唯一?

java - ThreadPoolExecutor中如何实现提交方法吞下异常,但执行-不

java - 在 Domino Java 代理中使用记录器

java - 如何将自动时间戳表条目从纪元时间更改为现在?

java - 这两种代码风格的区别有名字吗?

c# - 锁定两种方法并确保只有在线程上调用一种方法

c# - 线程池中的线程