我是Akka的新手,我想知道我应该如何处理将工作委托给其他(儿童)演员的演员,但是在哪里:
其中一些儿童演员必须按照特定的顺序参与;和
这些子演员中的一些可以以任何顺序参与,并且可以真正地与主要/父演员的动作异步执行
假设我有以下儿童演员(无论他们做什么):
// Grovy pseudo code
class ActorA extends UntypedActor {
@Override
void onReceive(Object message) {
if(message instanceof RunActorA) {
…
}
}
class ActorB extends UntypedActor {
@Override
void onReceive(Object message) {
if(message instanceof RunActorB) {
…
}
}
class ActorC extends UntypedActor {
@Override
void onReceive(Object message) {
if(message instanceof RunActorC) {
…
}
}
class ActorD extends UntypedActor {
@Override
void onReceive(Object message) {
if(message instanceof RunActorD) {
…
}
}
并说我有以下父级角色来调用它们:
class MasterParent extends UntypedActor {
ActorRef actorA
ActorRef actorB
ActorRef actorC
ActorRef actorD
MasterParent(ActorRef actorA, ActorRef actorA, ActorRef actorA, ActorRef actorA) {
super()
this.actorA = actorA
this.actorB = actorB
this.actorC = actorC
this.actorD = actorD
}
@Override
void onReceive(Object message) {
if(message instanceof ProcessData) {
ProcessData pData = message as ProcessData
Widget widget = pData.widget
RunActorA runA = new RunActorA(widget)
actorA.tell(runA, self)
// Somehow obtain a result from A, perhaps an “ResultOfA” object.
ResultOfA resultA = ??? // get from ActorA
RunActorB runB = new RunActorB(resultA)
RunActorC runC = new RunActorC(resultA)
actorB.tell(runB, self)
actorC.tell(runC, self)
// Somehow wait until both B and C return a result, say, ResultOfB and ResultOfC, respectively.
ResultOfB resultB = ??? // get from ActorB
ResultOfC resultC = ??? // get from ActorC
RunActorD runD = new RunActorD(resultB, resultC)
actorD.tell(runD, self)
}
}
}
如你看到的:
必须首先“参与”(由家长调用)“
ActorA
”,并且在“ MasterParent
”继续进行并参与/调用ActorB
,ActorC
或ActorD
之前,我们必须等待其响应。可以异步/并行地相互调用
ActorB
和ActorC
,但是MasterParent
必须先等待两者的响应,然后才能继续参与和调用ActorD
换句话说,当
ProcessData
收到MasterParent
消息时:运行
ActorA
并等待其返回结果;然后同时运行
ActorB
和ActorC
并等待它们的结果;然后运行
ActorD
我的主要问题是:如何实现这一目标(Java伪代码或示例倍受赞赏!)?
其次,更重要的是,因为我对演员还很陌生:这种亲子编排在阿卡语中是否“正常”?还是,Akka最佳实践是否通常会规定所有子代异步运行,而没有施加顺序/命令/编排?
最佳答案
首先,是的,因为MasterParent将工作委派给其他演员,所以将他们作为儿童演员是有意义的。
同样,您对ResultOfA的想法也相距不远。
这是您可以做到的一种方法:
ResultOfB resultB = null;
ResultOfC resultC = null;
@Override
void onReceive(Object message) {
if(message instanceof ProcessData) {
ProcessData pData = message as ProcessData
resultB = null;
resultC = null;
Widget widget = pData.widget
RunActorA runA = new RunActorA(widget)
actorA.tell(runA, self)
} else if (message instanceof ResultOfA) {
ResultOfA resultA = message as ResultOfA
actorB.tell(resultA)
actorC.tell(resultA)
} else if (message instanceof ResultOfB) {
resultB = message as ResultOfB
if (resultC != null) {
actorD.tell(composedResultBAndC)
}
} else if (message instanceof ResultOfC) {
resultC = message as ResultOfC
if (resultB != null) {
actorD.tell(composedResultBAndC)
}
} else if (message instanceof ResultOfD) {
//Do stuff with the result
}
}
每个子actor都将执行sender()。tell(resultX)的位置,以便主机可以接收结果。
ResultB和ResultC都需要,因此我在actor中保存了一些状态,该状态在ProcessData的每个新实例上都设置为null,因此在这种情况下无法将多个ProcessData发送到一个MasterParent。
如果您想不等待而将多个ProcessData消息发送到一个MasterParent,则需要使其保持无状态,因此可以在actorB和actorC上使用Ask Pattern并一起解析返回的期货。所以像:
Future futureA = actorB.ask(resultA)
Future futureB = actorC.ask(resultA)
然后compose them并注册一个回调,您在其中向actorD发送请求。
此代码为伪编码,因此不可运行。