CompletableFuture cf1 = CompletableFuture.supplyAsync(() -> {
System.out.println("enter into completableFuture()");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("start to out of completableFuture()");
return "a";
});
System.out.println("do something else");
cf1.thenApply(v -> v + " b").thenAcceptAsync(v ->
System.out.println(v)
);
System.out.println("finalize...");
//注释最后一行,无法得到预期结果
//TimeUnit.SECONDS.sleep(10);
得到引結果為:
do something else
enter into completableFuture()
finalize...
start to out of completableFuture()
a b
以上程式碼如果註解掉最後一行,無法得到預期結果。
為什麼一定要明確的讓程式sleep10秒呢?
某草草2017-06-15 09:24:15
見CompletableFuture.supplyAsync
的javadoc:
傳回一個新的 CompletableFuture,它由運行在
ForkJoinPool.commonPool()
中的任務異步完成,並透過呼叫給定的供應商來獲得值。
而ForkJoinPool.commonPool()
的javadoc:
傳回公共池實例。該池是靜態建置的;其運行狀態不受嘗試關閉或 shutdownNow 的影響。 然而,這個池和任何正在進行的處理都會在程式
System.exit
時自動終止。任何依賴非同步任務處理在程式終止之前完成的程式都應該在退出之前呼叫commonPool().awaitQuithesis
。
如果你把最後的sleep
改成ForkJoinPool.commonPool().awaitQuithesis(2, TimeUnit.SECONDS);
也能達到你預期的結果
某草草2017-06-15 09:24:15
搜尋一下:守護線程
當線程中只剩下守護線程時JVM就會退出,反之亦然還有任意一個用戶線程在,JVM都不會退出。
我們可以猜測CompletableFuture.supplyAsync啟動了一個守護線程,實際上CompletableFuture內部預設使用ForkJoinPool,該線程池初始化一個線程工廠類別:
defaultForkJoinWorkerThreadFactory = new DefaultForkJoinWorkerThreadFactory();
查看他的實現,每次都是創建守護程式。至於為什麼一定要主線程sleep就很好理解。