在Akka精心策划儿童演员

时间:2015-08-05 20:25:25

标签: java asynchronous akka actor

我是阿卡的新手,我想知道我应该如何处理将工作委托给其他(儿童)演员的演员,但其中:

  1. 其中一些儿童演员必须从事特定的订单;和
  2. 其中一些儿童演员可以参与任何顺序,并且可以真正与主/父演员的行为异步执行
  3. 假设我有以下儿童演员(无论他们做什么):

    // 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) {
                …
            }
        }
    

    并说我有以下调用它们的父actor:

    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之前的响应提前并参与/调用ActorBActorCActorD
    • ActorBActorC可以异步/并行调用,但是MasterParent必须等待来自两者的响应才能继续进行/调用{{1} }}

    换句话说,当ActorD收到ProcessData条消息时:

    1. 运行MasterParent并等待它返回结果;然后
    2. 同时运行ActorAActorB并等待两者的结果;然后
    3. 运行ActorC
    4. 我的主要问题是:我如何实现这一目标(Java伪代码或示例非常赞赏!)?

      第二,可辩论更重要的是,因为我对演员很陌生:这种类型的亲子编排在Akka中是“正常的”吗?或者,Akka最佳实践通常要求所有子项是异步运行的,没有强加序列/顺序/编排?

1 个答案:

答案 0 :(得分:1)

首先,是的,因为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),以便master接收结果。

ResultB和ResultC都是必需的,所以我在actor中保存了一些状态,在每个新的ProcessData实例上设置为null,因此在这种情况下不可能将多个ProcessData发送到一个MasterParent。

如果你想在不等待的情况下向一个MasterParent发送多个ProcessData消息,你需要保持它没有状态,因此可以在actorB和actorC上使用Ask Pattern并一起解决返回的未来。如下所示:

Future futureA = actorB.ask(resultA)
Future futureB = actorC.ask(resultA)

然后compose them并注册一个回调,在那里向actorD发送请求。

此代码伪编码,因此不可运行。