首頁  >  問答  >  主體

java - JDK8的CompletableFuture使用問題

        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秒呢?

伊谢尔伦伊谢尔伦2683 天前874

全部回覆(2)我來回復

  • 某草草

    某草草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);也能達到你預期的結果

    回覆
    0
  • 某草草

    某草草2017-06-15 09:24:15

    搜尋一下:守護線程
    當線程中只剩下守護線程時JVM就會退出,反之亦然還有任意一個用戶線程在,JVM都不會退出。
    我們可以猜測CompletableFuture.supplyAsync啟動了一個守護線程,實際上CompletableFuture內部預設使用ForkJoinPool,該線程池初始化一個線程工廠類別:

        defaultForkJoinWorkerThreadFactory = new DefaultForkJoinWorkerThreadFactory();

    查看他的實現,每次都是創建守護程式。至於為什麼一定要主線程sleep就很好理解。

    回覆
    0
  • 取消回覆