所以我在Akka中使用了不同的行为。当我执行这段代码时:
@Override
public Receive<CommonCommand> createReceive() {
return notYetStarted();
}
public Receive<CommonCommand> notYetStarted() {
return newReceiveBuilder()
.onMessage(RaceLengthCommand.class, message -> {
// business logic
return running();
})
.build();
}
public Receive<CommonCommand> running() {
return newReceiveBuilder()
.onMessage(AskPosition.class, message -> {
if ("some_condition") {
// business logic
return this;
} else {
// business logic
return completed(completedTime);
}
})
.build();
}
public Receive<CommonCommand> completed(long completedTime) {
return newReceiveBuilder()
.onMessage(AskPosition.class, message -> {
// business logic
return this;
})
.build();
}
我得到了以下日志:
21:46:41.038 [monitor-akka.actor.default-dispatcher-6] INFO akka.actor.LocalActorRef - Message [learn.tutorial._5_racing_game_akka.RacerBehavior$AskPosition] to Actor[akka://monitor/user/racer_1#-1301834398] was unhandled. [1] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
最初,RaceLengthCommand
消息被发送到notYetStarted()
行为。这工作正常。然后,这个行为应该转换到running()
行为,第二个行为应该接收消息AskPosition
。
但是根据我的测试,AskPosition
消息被传递给notYetStarted()
行为,这与我对这个概念的整体理解相矛盾。
我通过从running()
行为中复制onMessage()
部分并粘贴到notYetStarted()
行为中来确认这一点。
很显然,即使在我切换了行为之后,notYetStarted()
行为也确实在接收消息?为什么会发生这种情况??
1条答案
按热度按时间rekjcdws1#
看起来您的actor定义混合了OO和函数样式,并且在同一actor中使用这些样式之间的相互作用中遇到了一些问题。这种混淆的一些原因是Java API中的
Receive
是Behavior
而不是AbstractBehavior
。这可能是API早期发展的痕迹(我已经建议Akka的维护者在2.7中删除这个遗迹(由于二进制兼容性,这是最早的删除时间);与其中一些应用程序的通信还没有得出这种区别的原因,类似的Scala API中也没有这种区别)。免责声明:我倾向于只使用Scala函数API来定义actor。
在参与者模型中,参与者的状态(即它的字段)和行为(它如何响应它接收到的下一条消息)之间存在二元性:对于参与者之外的世界来说,它们是同一个,因为观察参与者状态的唯一方法(忽略像堆转储这样的东西)是观察它对消息的响应。当然,实际上,当前行为是参与者运行时表示中的一个字段,而在函数定义中,行为通常有状态字段。
行为定义的OO风格倾向于:
行为定义的功能风格倾向于:
(the这一区别类似于命令式编程(具有一个while/for循环,其中一个变量被更新)与函数式编程(偏好于定义一个递归函数,编译器在后台将其转换为一个循环)。
AbstractBehavior
API似乎假定消息处理程序是createReceive()
:在AbstractBehavior
中返回this
意味着返回到createReceive()
。相反,在函数样式中的Behaviors.same()
意味着“无论当前行为是什么,都不要改变它”。在一个AbstractBehavior
中存在多个sub-Behavior
/Receive
的情况下,这个差异很重要(当AbstractBehavior
中有一个Receive
时,这个差异就不重要了)。AbstractBehavior
中定义多个消息处理程序,则在消息处理程序中首选return Behaviors.same
而不是return this
。或者:每个AbstractBehavior
仅定义一个消息处理程序。*