[英]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.