简体   繁体   English

如何在 play framework 2.5 中编写异步操作?

[英]How to write async actions in play framework 2.5?

I wrote the following code to send an email as non-blocking action.我编写了以下代码以作为非阻塞操作发送电子邮件。 It's not working for more than 1 request.它不适用于超过 1 个请求。

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

As play.Promise is deprecated in play.2.5 (java).因为play.Promise在 play.2.5 (java) 中被弃用。 My previous code is not supporting.我以前的代码不支持。 So please give me proper solution to make my action as non-blocking.所以请给我适当的解决方案,使我的行动成为非阻塞。

If the function EmailService.sendVerificationMail is blocking, CompletableFuture only makes it non-blocking on the calling thread.如果函数EmailService.sendVerificationMail是阻塞的, CompletableFuture只会使它在调用线程上非阻塞。 In fact it is still blocking on other thread (probably the common ForkJoinPool ).事实上,它仍然在其他线程上阻塞(可能是常见的ForkJoinPool )。

This is not a problem if only several email tasks are running.如果只有几个电子邮件任务正在运行,这不是问题。 But if there are too many email tasks (say 100 or more), they will "dominate" the pool.但是,如果电子邮件任务太多(比如 100 个或更多),它们将“主导”池。 This causes "Convoy effect" and other tasks have to wait much more time to start.这会导致“车队效应”,其他任务必须等待更多时间才能开始。 This can badly damage the server performance.这会严重损害服务器性能。

If you have a lot of concurrent email tasks, you can create your own pool to handles them, instead of using the common pool.如果您有很多并发电子邮件任务,您可以创建自己的池来处理它们,而不是使用公共池。 Thread pool is better than fork join pool because it does not allow work-stealing.线程池比 fork 连接池更好,因为它不允许窃取工作。

Or you can find the asynchronous APIs of EmailService , or implement them on your own if possible.或者您可以找到EmailService的异步 API,或者如果可能的话,您可以自己实现它们。

To answer the other question, now Play 2.5 uses CompletionStage for the default promise.为了回答另一个问题,现在 Play 2.5 使用CompletionStage作为默认承诺。 It should work if you just use CompletionStage .如果您只使用CompletionStage它应该可以工作。

Some example code here.一些示例代码在这里。 Note the use of CompletionStage in the return type.注意返回类型中CompletionStage的使用。

public CompletionStage<Result> testAction() {
    return CompletableFuture
            .supplyAsync(() -> EmailService.sendVerificationMail(appUser, mailString), EmailService.getExecutor())
            .thenApply(i -> ok("Got result: " + i));
}

For more details, you may check the Java Migration Guide on Play's site.有关更多详细信息,您可以查看 Play 站点上的Java 迁移指南

import java.util.concurrent.CompletableFuture;

public static CompletableFuture<Result> asynchronousProcessTask() {
        final CompletableFuture<Boolean> promise = CompletableFuture
                .supplyAsync(() -> Locate365Util.doTask());
        return promise.thenApplyAsync(
                (final Boolean i) -> ok("The Result of promise" + promise));
    }

** doTask() method must return boolean value

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM