2016-04-27 58 views
1

我写了下面的代码发送电子邮件为非阻塞操作。 它不适用于多个请求。如何在play framework 2.5中编写异步操作?

CompletableFuture.supplyAsync(() -> 
EmailService.sendVerificationMail(appUser , mailString)). 
    thenApply(i -> ok("Got result: " + i)); 

由于play.Promise在play.2.5(java)中已弃用。我以前的代码不支持。所以请给我适当的解决方案,使我的行动非阻塞。

+0

提问的好方法:https://codeblog.jonskeet.uk/2010/08/29/writing-the-perfect-question/ – TheGameiswar

+0

可以请你解释一下我的问题出了什么问题。其实这是我的第一个问题堆栈溢出.. –

+1

如果你给了更多的细节,你可能会得到更多的关注。在别人的鞋子回答你自己的想法 – TheGameiswar

回答

2

如果函数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

+0

谢谢@HKTonyLee。我会尽力实现你的代码。你可以告诉我几个异步电子邮件API。? –

+0

嗨@HKTonuLee,上面的代码也阻止了这个函数。当我尝试下面的代码时,它变成了非阻塞,但有时它不工作。 –

+0

嗨@HKTonuLee,上面的代码也阻止了这个函数。当我尝试下面的代码时,它变成了非阻塞,但有时它不工作。公共结果sendEmail(){CompletableFuture.supplyAsync(() - > EmailService.sendVerificationMail(appUser,“您的帐户的电子邮件验证”))然后应用(我 - >好(“得到的结果:”+我)); return ok(); }这种方法工作正常我不明白上述两者之间有什么区别请帮助我谢谢 –