簡體   English   中英

`thenRunAsync(...)`和`CompletableFuture.runAsync(()-> {…}))是否完全相關?

[英]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 內容實際上是在以不同的方式說出我所懷疑的內容。

runAsyncthenRunAsync執行異步的Runnable taks

使用此階段的默認異步執行工具執行給定操作

問題:換句話說,then * Async方法終止符(完成方法)是否在原始線程中返回前一個鏈的結果,然后生成一個新線程來執行其余操作?

答案:否,從文檔中可以完成一個階段,或者兩個階段都完成,或者兩個階段都可以觸發一個階段的執行 。因此,基本上可以根據程序員對該部分的編碼方式來返回結果,但是現在情況下(使用thenRunAsync ),結果將在第一階段完成后返回,因為在第二階段thenRunAsync您將第一階段的結果作為輸入,但不返回任何內容。

接口完成階段

一個階段的執行可以由一個階段的完成或兩個階段的全部或兩個階段中的一個觸發。 使用帶有前綴的方法來安排對單個階段的依賴。 通過兩個階段都完成而觸發的結果可以使用相應命名的方法組合其結果或效果。 由兩個階段中的任何一個觸發的結果不能保證哪個結果或效果用於從屬階段的計算。

第一個示例和第二個示例之間也存在細微差異

例如:1。在這個例子中Runnable任務得到執行異步返回結果之前,這兩個FunctionthenApplyRunnablerunAsync將同時執行

return mainTasksFuture.thenApply(response -> {
 CompletableFuture.runAsync(() -> {
   // extra tasks
   });
  return response;
 });

實施例:2在這個例子中Runnable從任務thenRunAsync將完成之后被執行FunctionthenApply

return mainTasksFuture.thenApply(response -> {
return response;
}).thenRunAsync(() -> {
  // extra tasks
});

你寫了

似乎只是純粹基於方法名稱,對於CompletableFutures的新手來說。

好吧,方法名稱正確地反映了方法的作用。 runAsyncthenRunAsync啟動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.

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