为什么CompletableFuture的runAsync方法不调用get()就不会执行?
CompletableFuture runAsync 执行时机问题解答
你给出的代码示例如下:
CompletableFuture result= CompletableFuture.runAsync(()->{ System.out.println("1st Task Completed"); });
首先给出明确结论:不是只有调用get()方法时,runAsync提交的任务才会执行,你遇到的无输出现象是JVM的线程退出机制导致的,具体原理如下:
CompletableFuture.runAsync()被调用的瞬间,任务就会被提交到默认的ForkJoinPool.commonPool()线程池等待调度,只要线程池有可用工作线程,任务就会立刻启动执行,和后续是否调用get()没有任何关联。- 未调用
get()时看不到输出的核心原因:ForkJoinPool.commonPool()创建的工作线程默认是 守护线程,JVM判断是否需要终止进程的标准是「当前所有存活的非守护线程是否全部执行完毕」。main线程属于非守护线程,未调用get()时,main线程提交完异步任务后会直接运行结束,此时JVM检测不到其他存活的非守护线程,就会直接终止进程,异步任务还没来得及被调度执行、或者还没运行完就被销毁,自然不会打印对应内容。 - 调用
get()后能看到输出的原因:get()是阻塞方法,会让调用它的main线程进入阻塞等待状态,直到异步任务执行完成后才会恢复运行,相当于main线程主动等待异步任务执行完毕,所以可以看到打印内容。
你可以通过简单修改代码验证上述逻辑:提交完异步任务后不调用get(),而是添加一行 Thread.sleep(1000) 让main线程休眠1秒,同样可以看到打印输出,这也能证明get()不是触发任务执行的必要条件。
内容的提问来源于stack exchange,提问作者Rajanikanta Pradhan
相关产品推荐
相关产品推荐

