如果函數EmailService.sendVerificationMail
被阻塞,CompletableFuture
只會使其在調用線程上非阻塞。實際上它仍然在其他線程上阻塞(可能是常見的ForkJoinPool
)。
如果只有幾個電子郵件任務正在運行,這不是問題。但是如果有太多的電子郵件任務(比如說100或更多),他們會「控制」這個池。這會導致「Convoy效應」,其他任務必須等待更多的時間才能開始。這可能嚴重損害服務器性能。
如果您有很多併發電子郵件任務,則可以創建自己的池來處理它們,而不是使用公共池。線程池比fork join更好,因爲它不允許偷工作。
或者您可以找到EmailService
的異步API,或在可能的情況下自行實施它們。
要回答另一個問題,現在Play 2.5使用CompletionStage
作爲默認承諾。它應該工作,如果你只是使用CompletionStage
。
這裏有一些示例代碼。請注意在返回類型中使用CompletionStage
。
public CompletionStage<Result> testAction() {
return CompletableFuture
.supplyAsync(() -> EmailService.sendVerificationMail(appUser, mailString), EmailService.getExecutor())
.thenApply(i -> ok("Got result: " + i));
}
有關更多詳細信息,請查看Play網站上的Java Migration Guide。
提問的好方法:https://codeblog.jonskeet.uk/2010/08/29/writing-the-perfect-question/ – TheGameiswar
可以請你解釋一下我的問題出了什麼問題。其實這是我的第一個問題堆棧溢出.. –
如果你給了更多的細節,你可能會得到更多的關注。在別人的鞋子回答你自己的想法 – TheGameiswar