簡體   English   中英

如果手動完成,則不會調用 CompletableFuture 回調

[英]CompletableFuture callback not called if completed manually

CompletableFuture的這個基本示例中,我異步運行了一個任務,當它完成時,應該觸發一個異步回調。

在我開始運行任務后一秒鍾,在它完成之前,我完成了它。 之后,我不再看到它運行異步回調。

public static void main(String[] args) throws InterruptedException {
    runTask();
    Thread.sleep(1000);
    completableFuture.complete("Test");
    Thread.sleep(4000);
}

public static void runTask() {
    completableFuture = CompletableFuture.supplyAsync(() -> {
        System.out.println("Running...");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("...finished");
        return "finished task";
    })
    .thenApplyAsync(s -> {
        System.out.println("Apply on result: " + s);
        return "Result: " + s;
    })
}

結果是:

Running...
...finished

問題是,如果我添加另一個回調,那么它會運行第一個而不是第二個。

.thenApplyAsync(s -> {
    System.out.println("Second apply with result: " + s);
    return "Result: " + s;
})

那么結果是:

Running...
...finished
Apply on result: finished task

閱讀文檔后,我了解到所有回調都會被調用,即使未來是手動完成的。 我在這里錯過了什么嗎?

我想如果你寫得稍微不同,它應該是有道理的:

public static void runTask() {

    CompletableFuture<String> one = CompletableFuture.supplyAsync(() -> {
        System.out.println("Running...");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("...finished");
        return "finished task";
    });

    CompletableFuture<String> two = one.thenApplyAsync(s -> {
        System.out.println("Apply on result: " + s);
        return "Result: " + s;
    });

    completableFuture = two;
} 

所以,在你的情況下, one開始就好了,但是在two甚至可以開始之前,你發出completableFuture.complete("Test"); . 因此,當one完成時, thenApplyAsync沒有任何內容,因為那個已經完成了。

當您再添加一個階段時,您基本上會得到:

....
CompletableFuture<String> two = one.thenApplyAsync(s -> {
     System.out.println("Apply on result: " + s);
     return "Result: " + s;
});

CompletableFuture<String> three = two.thenApplyAsync(s -> {
     System.out.println("Second apply with result: " + s);
     return "Result: " + s;
});

completableFuture = three;

你可能會看到這里發生了什么,甚至不用我解釋。


為此,我看不出文檔在哪里可以清楚地說明這一點。 我想我們需要通過以下方式在package 文檔中看到這一點:

當兩個或更多線程嘗試完成、完成異常或取消 CompletableFuture 時,只有其中一個成功。

這在某種程度上意味着,如果某個階段尚未開始,但由其他人完成,則在外部complete它; 那個階段根本不會運行。 這是有道理的,但 package 文檔可能更清楚,imo。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM