簡體   English   中英

然后應用於CompletableFuture

[英]thenApply in CompletableFuture

在下面的代碼中

public CompletableFuture<String> getMyFuture(String input)
    {   
        CompletableFuture<String> future = new CompletableFuture<String>().thenApply((result) -> result+ "::");
        ExecutorService service = Executors.newFixedThreadPool(6);
        service.submit(() -> {      
            try {
                future.complete(getResult(input));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        return future;
    }

    public String getResult(String input) throws InterruptedException
    {
        Thread.sleep(3000);
        return "hello "+ input +" :" + LocalTime.now();
    }

我期望輸出包含尾部的“ ::”,但程序不是“ hello first:16:49:30.231”我的apply實現正確嗎?

您正在調用第一行獲得的CompletionStage complete()方法(在此處稱為“ thenApply”方法)。

如果您打算用某個字符串值( future.complete(getResult(input)) )完成CompletableFuture並應用一些函數,則最好將thenApply()放在最后(返回未來)。

public CompletableFuture<String> getMyFuture(String input)
    {
        CompletableFuture<String> future = new CompletableFuture<String>();
        ExecutorService service = Executors.newFixedThreadPool(6);
        service.submit(() -> {
            try {
                future.complete(getResult(input));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        return future.thenApply(result -> result+ "::");
    }

我不知道如何以更容易理解的方式解釋它。 但簡而言之: 您正在對 Runnable 錯誤的對象引用調用complete()方法

您正在創建兩個 CompletableFuture實例。 第一個是通過new CompletableFuture<String>()創建的,它將永遠不會完成,您甚至不會保留對其進行引用的引用,從而無法完成。

通過在第一個函數上調用.thenApply((result) -> result+ "::")創建的第二個函數,可以在第一個函數完成后通過評估指定的函數來完成,並使用第一個函數的結果作為函數的參數。 但是,由於第一個永遠不會完成,因此該功能變得無關緊要。

但是CompletableFuture實例可以由任何人完成,而不僅僅是傳遞給鏈接方法的函數。 完成的可能性甚至在班級名稱中突出顯示。 如果進行了多次完成嘗試,那么結果將是第一個贏得比賽,並且所有后續完成嘗試都將被忽略。 在您的代碼中,您只有一次完成嘗試,它將使用getResult返回的值成功完成它,而無需進行任何修改。

您可以更改代碼以保留對第一個CompletableFuture實例的引用,以手動complete它,以便使用傳遞給thenApply的函數來完成第二個thenApply ,但是另一方面,這里不需要手動完成:

public CompletableFuture<String> getMyFuture(String input) {   
    ExecutorService service = Executors.newFixedThreadPool(6);
    return CompletableFuture.supplyAsync(() -> getResult(input), service)
                            .thenApply(result -> result + "::");
}
public String getResult(String input) {
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(3));
    return "hello "+ input +" :" + LocalTime.now();
}    

將執行程序指定為supplyAsync ,將使用該執行程序對函數進行評估。 不需要更多。

不用說,這只是舉例。 您永遠不應創建一個臨時線程池執行程序,因為線程池執行程序的全部目的是允許重用線程(並且您僅使用這六個線程之一),並且在使用后應將其關閉。

暫無
暫無

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

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