Home > database >  how does ThenRun in CompletableFuture work?
how does ThenRun in CompletableFuture work?

Time:04-18

The main function outputs only 1, 2 and 3. Why does the Runnable in thenRun not run and print 4 as well?

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();
    }
  }

However, when I change the doSomething function as shown below, all the numbers 1,2,3 and 4 will be printed.

  static void doSomething() {
    return;
  }

CodePudding user response:

You invoke doSomething() from printAsync() and each invocation puts the invoking thread to sleep for 100ms. Therefore you don't wait long enough to see the output of 4.

You can use join as suggested in the comments to wait until all submitted tasks are finished. Or (to help understand what is happening) you can add a parameter to doSomething to specify the amount of ms to sleep and wait a bit longer in your main thread, as shown below.

It is not that the printAsync(4) is not executed. Rather, the jvm terminates the process because all non-daemon threads (in this case the main thread) are done before that point.

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);
    }
  }

CodePudding user response:

As mentioned in the comments, .thenRun(() -> printAsync(4).join()).join(); will create another CompletableFuture and complete it, giving you the expected output.

  • Related