CompletableFuture 中的 ThenRun 如何工作?

how does ThenRun in CompletableFuture work?

main函数只输出1、2、3,为什么thenRun中的Runnable不运行打印4呢?

import java.util.concurrent.CompletableFuture;
import java.lang.Thread;

  class CF {
  static void doSomething() {
    try {
      Thread.sleep(100);
    } catch(InterruptedException e) {
      System.out.println("ggwp");
    }
  }
 
  static CompletableFuture<Void> printAsync(int i) {
    return CompletableFuture.runAsync(() -> {
      doSomething();
      System.out.print(i);
      System.out.println(Thread.currentThread().getName());
    });
  }
 
  public static void main(String[] args) {
    printAsync(1).join();
    CompletableFuture.allOf(printAsync(2), printAsync(3))
      .thenRun(() -> printAsync(4));
    doSomething();
    }
  }

但是,当我如下所示更改 doSomething 函数时,将打印所有数字 1、2、3 和 4。

  static void doSomething() {
    return;
  }

如评论中所述,.thenRun(() -> printAsync(4).join()).join(); 将创建另一个 CompletableFuture 并完成它,为您提供预期的输出。

您从 printAsync() 调用 doSomething(),每次调用都会使调用线程休眠 100 毫秒。因此,您不会等待足够长的时间来查看 4.

的输出

您可以按照评论中的建议使用join等待所有提交的任务完成。或者(为了帮助理解正在发生的事情)您可以向 doSomething 添加一个参数来指定要在主线程中休眠并等待更长时间的毫秒数,如下所示。

不是没有执行printAsync(4)。相反,jvm 终止了进程,因为所有 non-daemon 线程(在本例中为主线程)都在该点之前完成。

import java.util.concurrent.CompletableFuture;
import java.lang.Thread;

  class CF {
  static void doSomething(long sleep) {
    try {
      Thread.sleep(sleep);
    } catch(InterruptedException e) {
      System.out.println("ggwp");
    }
  }
 
  static CompletableFuture<Void> printAsync(int i) {
    return CompletableFuture.runAsync(() -> {
      doSomething(100);
      System.out.print(i);
      System.out.println(Thread.currentThread().getName());
    });
  }

  public static void main(String[] args) {
    printAsync(1).join();
    CompletableFuture.allOf(printAsync(2), printAsync(3))
      .thenRun(() -> printAsync(4));
    doSomething(500);
    }
  }