[英]Are `thenRunAsync(…)` and `CompletableFuture.runAsync(() -> { … });` related at all?
我需要執行一些額外的任務,但要讓原始線程結束, 例如,發回HTTP響應。
我想我可以做到這一點:
return mainTasksFuture.thenApply(response -> {
CompletableFuture.runAsync(() -> {
// extra tasks
});
return response;
});
但是我記得有一個thenRunAsync
。 是
return mainTasksFuture.thenApply(response -> {
return response;
}).thenRunAsync(() -> {
// extra tasks
});
基本上是做同一件事的另一種方法? 換句話說, then*Async
方法終止符(完成方法)是否在原始線程中返回前一個鏈的結果,然后生成一個新線程來執行其余的?
我幾乎可以肯定,答案是否定的 。 似乎對於CompletableFutures剛接觸的人來說 ,可能完全基於方法名稱。 我想得到一個確認,以防萬一我讀到有關ForkJoinPool.commonPool
內容實際上是在以不同的方式說出我所懷疑的內容。
runAsync
和thenRunAsync
執行異步的Runnable
taks
使用此階段的默認異步執行工具執行給定操作
問題:換句話說,then * Async方法終止符(完成方法)是否在原始線程中返回前一個鏈的結果,然后生成一個新線程來執行其余操作?
答案:否,從文檔中可以完成一個階段,或者兩個階段都完成,或者兩個階段都可以觸發一個階段的執行 。因此,基本上可以根據程序員對該部分的編碼方式來返回結果,但是現在情況下(使用thenRunAsync
),結果將在第一階段完成后返回,因為在第二階段thenRunAsync
您將第一階段的結果作為輸入,但不返回任何內容。
一個階段的執行可以由一個階段的完成或兩個階段的全部或兩個階段中的一個觸發。 使用帶有前綴的方法來安排對單個階段的依賴。 通過兩個階段都完成而觸發的結果可以使用相應命名的方法組合其結果或效果。 由兩個階段中的任何一個觸發的結果不能保證哪個結果或效果用於從屬階段的計算。
第一個示例和第二個示例之間也存在細微差異
例如:1。在這個例子中Runnable
任務得到執行異步返回結果之前,這兩個Function
從thenApply
和Runnable
從runAsync
將同時執行
return mainTasksFuture.thenApply(response -> {
CompletableFuture.runAsync(() -> {
// extra tasks
});
return response;
});
實施例:2在這個例子中Runnable
從任務thenRunAsync
將完成之后被執行Function
從thenApply
return mainTasksFuture.thenApply(response -> {
return response;
}).thenRunAsync(() -> {
// extra tasks
});
你寫了
似乎只是純粹基於方法名稱,對於CompletableFutures的新手來說。
好吧,方法名稱正確地反映了方法的作用。 runAsync
和thenRunAsync
啟動Runnable
的異步執行並返回一個future,該異步執行完成后將完成。 因此,名稱的相似性是合理的。
根本上不同的是您的代碼。
在這個變體中
return mainTasksFuture.thenApply(response -> {
CompletableFuture.runAsync(() -> {
// extra tasks
});
return response;
});
您將完全忽略runAsync
返回的將來,因此,一旦觸發了異步操作,則將完成thenApply
返回的將來。 在“額外任務”仍同時運行時,調用方可以檢索結果值。
與...相比
return mainTasksFuture.thenApply(response -> {
return response;
}).thenRunAsync(() -> {
// extra tasks
});
thenApply
完全過時了,因為它什么也沒做。 但是您要返回的是thenRunAsync
返回的將來,它將在Runnable
的異步執行完成並且類型為CompletableFuture<Void>
,因為runnable不會產生值(將來將以null
)。 在例外情況下,它將完成,但mainTasksFuture
,但在成功情況下,它將不通過結果值。
如果第一個變體符合您的實際意圖(調用者不應依賴於額外任務的完成),則只需將它們建模為依賴項即可:
mainTasksFuture.thenRunAsync(() -> {
// extra tasks
});
return mainTasksFuture; // does not depend on the completion of extra task
否則,請使用變體2(減去過時的東西)
return mainTasksFuture.thenRunAsync(() -> {
// extra tasks
}); // depends on the completion of extra task but results in (Void)null
如果不需要結果值。 否則,您可以使用
return mainTasksFuture.thenApplyAsync(response -> {
// extra tasks
return response;
}); // depends on the completion of extra task and returns original result
它與
return mainTasksFuture.thenCompose(response ->
CompletableFuture.runAsync(() -> {
// extra tasks
}).thenApply(_void -> response));
這不會忽略runAsync
返回的未來,但與thenApplyAsync
相比,這種復雜性沒有任何優勢。
另一種選擇是
return mainTasksFuture.whenComplete((response,failure) -> {
if(failure == null) {
// extra tasks
}
});
因為當額外的任務完成時, whenComplete
返回的whenComplete
將以原始的whenComplete
結果完成。 但是,即使最初的未來異常完成,也始終會評估該函數,因此,如果不需要,則需要另一個條件。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.