使用当前参与者进程中参与者的响应



我对如何以非阻塞方式解决此场景感到困惑。

考虑两个参与者Actor1Actor2

Actor1

Map<Int, Int> foo() {
List<String> finalList = foo_2();
Map<Int, Int> finalMap = // do stuff with finalList to get Map<Int, Int>;
return finalMap;
}
List<String> foo_2() {

CompletableFuture<List<String>> Querylist = ask(Actor2)
Querylist.get();

return QueryList;
}

当前在foo_2中,Querylist.get()是一个阻塞调用。我想以一种非阻塞的方式解决这个问题。我在Actor1中为Actor2创建了一个消息适配器,因此Actor2发送的任何消息都将由Actor1处理。

我使用了以下方法来修改阻塞调用

Map<Int, Int> foo() {
CompletionStage<List<String>> finalList = foo_2();
finalList.whenComplete(
// what to do here? 
)
// Map<Int, Int> finalMap = // do stuff with finalList to get Map<Int, Int>;
return finalMap;
}
CompletionStage<List<String>> foo_2() {

CompletionStage<List<String>> Querylist = ask(Actor2)


return QueryList;
}

我不知道如何正确使用CompletionStage构造来获得与阻塞futures.get()调用相同的结果。

如果您使用的是Akka-Typed(从标记中隐含),那么您根本不需要future或消息适配器。只需使用ActorContext.ask

请参阅文档,了解两个参与者之间的请求响应和询问。

一般来说,您可以去掉foofoo_2方法,将已设置的消息适配器移动到ActorContext.ask调用中,并将以前调用foo的实例替换为对ActorContext.ask的调用。如果参与者向导致询问的消息发送的回复取决于对询问的响应,那么一个好的做法是将所需的状态部分嵌入适配器生成的消息中。

您可以使用pipeToSelf,请参阅https://doc.akka.io/docs/akka/current/typed/interaction-patterns.html#send-将来的结果发送给自己,将请求的结果发送到参与者本身。与尝试直接在foo()中获取finalList的值(这只有在阻塞get的情况下才可能)不同,foo(()的结果可以发送到actor本身,在这种情况下,您可以像处理任何其他消息一样处理它。为此创建一个特定的消息类型是很好的做法。

您还应该了解CompletionStage方法,最重要的是thenApply(https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletionStage.html#thenApply-java.util.function.function-),它使转换结果成为可能,例如,从finalList创建Map,以及例如从Map创建MapMessage。然后,您将像actor中的任何其他消息一样处理MapMessage

最新更新