How to use CompletableFuture in java 8 to start an

2020-04-16 02:59发布

问题:

I have the following code (more or less):

ExecutorService executor = Executors.newFixedThreadPool(10);
CompletableFuture
    .supplyAsync(()->{
        return longRunningMethodThatReturnsBoolean();
    }, executor)
    .thenAcceptAsync(taskResult -> {
        logResult();
        executor.shutdown(); 
    }, executor);

This allows the code in the main thread to continue, however I was expecting the main thread to die when it finished and the future to keep working in it's own thread, but the main thread stays alive until the CompletableFuture finishes even though the main thread isn't doing anything anymore.

I'm kind of new to this, am I missing something? Is it even possible?

Any help will be greatly appreciated!!!

回答1:

Actually, if your main thread doesn't wait on the CompletableFuture's .get() or any other blocking method, then it dies as soon as it reaches the end of the main method.

You can check it using the following example:

public static void main(String[] args){
    final Thread mainThread = Thread.currentThread();
    ExecutorService executor = Executors.newFixedThreadPool(10);
    CompletableFuture
            .supplyAsync(()-> {
                try {
                    Thread.sleep(1000);
                    //prints false
                    System.out.println("Main thread is alive: " + mainThread.isAlive());
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return true;
            }, executor)
            .thenAcceptAsync(taskResult -> {
                System.out.println("LongRunning is finished");
                executor.shutdown();
            }, executor);
}

But the Java Virtual Machine continues to execute threads until either of the following occurs

  • The exit method of class Runtime has been called and the security manager has permitted the exit operation to take place.
  • All threads that are not daemon threads have died, either by returning from the call to the run method or by throwing an exception that propagates beyond the run method.

It means that even though the main thread is dead, the virtual machine continues to work because all threads created by the Executors.newFixedThreadPool(10) are non-daemon. You can read about it in the documentation of the defaultThreadFactory() method in the Executors class:

Each new thread is created as a non-daemon thread with priority set to the smaller of Thread.NORM_PRIORITY and the maximum priority permitted in the thread group



回答2:

The main thread waits until all the other non-daemon threads are done before cleaning up and exiting the process:

http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/9b0ca45cd756/src/share/vm/runtime/thread.cpp#l3629