java - 如果链中的第一个方法是异步的,则方法调用链(CompletableFuture API)是否会异步执行?

标签 java multithreading asynchronous concurrency completable-future

我正在研究 CompletableFuture API,有一个例子:

CompletableFuture.completedFuture(url)
                 .thenComposeAsync(this::readPage, executor)
                 .thenApply(this::getImageURLs)
                 .thenApply(this::saveFoundImages)
                 .....
我有一个问题:如果我调用 thenComposeAsync(...)方法作为第一个方法,链中的其他方法是否会在 executor 中执行?我通过参数传递了哪个,或者我应该使用 async 调用其他方法以在特定执行器中异步执行?

最佳答案

好的,所以CompletableFuture中有3种方法.例如:

  • thenApply()
  • thenApplyAsync(Function) (没有执行者)
  • thenApplyAsync(Function, Executor) (与执行人)

  • 最后一个表示这个 Action 会在Executor中执行。你传递给它,这是最明显的一个。
    第二个表示 Action 在ForkJoinPool中执行.
    第一个更有趣。该文档通过以下方式使它听起来很容易:

    Actions supplied for dependent completions of non-async methods may be performed by the thread that completes the current CompletableFuture, or by any other caller of a completion method


    你需要开始把它分成更小的部分。你需要了解的是有线程完成某个CompletableFuture ,有一些线程对其执行一些操作,也有一些线程链接某些相关的操作。潜在地,这些都是不同的线程。这就是一切的开始:
  • 如果相关操作已被链接,将调用 complete 的线程将成为执行此操作的线程。
  • 如果 future 已经完成,那么链接 Action 的线程将执行它。

  • 由于上述步骤没有线性 Action ,因此实际上不可能确定您的 thenApply 在哪个线程中。将执行,至少有 100% 的确定性。该 Action 可以在以下任何一个中执行:
  • 调用 complete/completeExceptionally 的线程
  • 链接 thenApply 的线程
  • 调用 join/get 的线程

  • 以上任何一种情况都有可能。如果你真的想要我做了一个相当有趣的test here ,证明了上面的一些事情。

    我不想选择其他答案,但他提出了一个相当有趣的观点,我在乞讨时也很困惑:

    In your example: After .thenComposeAsync also all the following chained futures will get completed by executor.


    我们可以很容易地证明这是不正确的:
     CompletableFuture<String> future1 = CompletableFuture.completedFuture("a");
     CompletableFuture<String> future2 = future1.thenApplyAsync(x -> "b" + x, Executors.newCachedThreadPool());
    
     LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
    
     CompletableFuture<String> future3 = future2.thenApply(x -> {
          System.out.println(Thread.currentThread().getName());
          return x + "c";
     });
     future3.join();
    
    如果你运行它,你会看到main实际执行 thenApply ,而不是池中的线程。

    关于java - 如果链中的第一个方法是异步的,则方法调用链(CompletableFuture API)是否会异步执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65685715/

    相关文章:

    python - 在python和qt中同时下载文件

    java - 使用 SwingWorker 在 GUI 中添加进度条

    asp.net - 当 IIS 已经处理请求并发时,为什么要使用异步 Controller ?

    android - BufferedReader 读取在线文本文件而不在文件中缓存文本?

    java - Web 服务中 Spring 管理的 Bean 的竞争条件

    java - ReactiveX Backpressure 没有按预期工作

    java - 我无法将 css 文件链接到我的元素

    java - Hibernate PostUpdateEvent null 旧状态

    java - 具有多个订阅者和事件的 RxJava 并发

    asynchronous - Arduino - 无延迟提示音