我正在尝试创建一种在Play中以特定方式处理阻止操作的方法。首先,我描述了我的目标是什么,我到目前为止所管理的是什么。如果我走在正确的轨道上,你能告诉我 - 如果是的话,你能帮我理解如何完成代码吗?如果不是正确的方法,你可以建议一个更好的选择吗? 非常感谢你的帮助
目的: 希望将所有阻塞操作发送到一个线程,以便异步处理单独的线程。进入的新请求不会占用更多线程,而是将它们放入队列(或任何类似的)中以由单个线程处理。对于由额外线程异步处理的每个项目,必须收集一些文本并将其返回给浏览器。
因此,在阅读了docs和SO问题之后,似乎必须使用actor。我喜欢演员的概念,但之前从未使用过它们,所以我还在学习。这就是我所拥有的:
package models;
import java.io.*;
import play.mvc.*;
import play.libs.*;
import play.libs.F.*;
import akka.actor.*;
public class ActorTest extends UntypedActor {
static BufferedReader reader = new BufferedReader(new InputStreamReader(
System.in));
@Override
public void onReceive(Object message) throws Exception {
if (message instanceof String) {
getSender().tell(
"You sent me " + ((String) message)
+ " and the consol replied with "
+ reader.readLine(), getSelf());
} else
unhandled(message);
}
}
正如您所看到的,阻塞操作是readLine() - 只是一种测试方法。
这是怎么做的?如果是这样,我假设从控制器,我有些如何创建异步结果或使用promises的东西。 [ Handling asynchronous results ]。
情侣问题,如何向演员发送消息并获得回复?我的意思是我可以通过tel()调用获得结果吗? 我如何确保更多的线程不被占用并且所有操作都进入队列 - 或者这是否已由演员处理?
请您提供可以执行此操作的示例控制器操作吗?
非常感谢您的帮助。
PS FYI我对这一切都很陌生,所以为了进入这个阶段,我发现这些文档很有用 - Akka演员页面,当然还有一些关于演员的维基页面。
[编辑] 对不起,我说单线程,但它可能是一个线程池 - 只要只使用分配的线程/线程池来处理阻塞而不是任何其他线程。
答案 0 :(得分:2)
您可以使用ask(而不是tell)向Akka演员发送消息。它将返回一个Future,然后您可以映射到Promise<Result>
。
但是,如果你不需要,你根本不需要使用Akka。您可以简单地使用Futures / Promises在后台运行阻止操作。
在任何一种方法中,您最终都会得到一个Future,您可以在将来完成请求。
...
import play.libs.F.*;
public static Promise<Result> index() {
Promise<Integer> promiseOfInt = Promise.promise(
new Function0<Integer>() {
public Integer apply() {
// long-running operation (will run in separate thread)
return 42;
}
});
return promiseOfInt.map(
new Function<Integer, Result>() {
public Result apply(Integer i) {
// 'i' is the result after Promise is complete
return ok("Got result: " + i);
}
});
}
如果您使用的是Akka,则需要将从Future
返回的ask
转换为Play Promise
,如下所示:
public static Promise<Result> index() {
ActorRef myActor = Akka.system().actorFor("user/my-actor");
return Promise.wrap(ask(myActor, "hello", 1000)).map(
new Function<Object, Result>() {
public Result apply(Object response) {
return ok(response.toString());
}
});
}
...
import play.libs.F.*;
public static Result index() {
Promise<Integer> promiseOfInt = play.libs.Akka.future(
new Callable<Integer>() {
public Integer call() {
// long-running operation (will run in separate thread)
return 42;
}
});
return async(
promiseOfInt.map(
new Function<Integer,Result>() {
public Result apply(Integer i) {
// 'i' is the result after Promise is complete
return ok("Got result: " + i);
}
}));
}
如果您使用的是Akka,则需要将从Future
返回的ask
转换为Play Promise
,如下所示:
public static Result index() {
ActorRef myActor = Akka.system().actorFor("user/my-actor");
return async(
Akka.asPromise(ask(myActor,"hello", 1000)).map(
new Function<Object,Result>() {
public Result apply(Object response) {
return ok(response.toString());
}
}
)
);
}