【发布时间】:2015-08-30 19:23:15
【问题描述】:
我有这种情况:
-
ActorA每 30-40 秒发送一次ActorB启动/停止消息 -
ActorA发送ActorB字符串以打印(总是) -
ActorB必须打印他收到的字符串,但前提是ActorA只发送了一个开始消息
我的代码:
case object Start
case object Stop
case object TriggerStateChange
case object SendMessage
class ActorB extends Actor with Stash {
override def receive: Receive = {
case Start =>
context.become(printingBehavior, false)
unstashAll()
case x => stash()
}
def printingBehavior: Receive = {
case msg: String => println(msg)
case Stop => context.unbecome()
}
}
class ActorA(val actorB: ActorRef) extends Actor {
var counter = 0
var started = false
override def preStart: Unit = {
import context.dispatcher
this.context.system.scheduler.schedule(0 seconds, 5 seconds, self, TriggerStateChange)
this.context.system.scheduler.schedule(0 seconds, 1 seconds, self, SendMessage)
}
override def receive: Actor.Receive = {
case SendMessage =>
actorB ! "Message: " + counter
counter += 1
case TriggerStateChange =>
actorB ! (if (started) {
started = false
Stop
} else {
started = true
Start
})
}
}
object Akka {
def main(args: Array[String]) = {
val system = ActorSystem.create("TestActorSystem")
val actorB = system.actorOf(Props(classOf[ActorB]), "ActorB")
val actorA = system.actorOf(Props(classOf[ActorA], actorB), "ActorA")
system.awaitTermination()
}
}
我使用了这个代码suggested by another user,但是我有一个问题。
ActorB 应在收到停止消息后立即停止(因此,如果在打印 M1 时收到 M1-M2-M3 和停止消息,则不得打印 M2 和 M3)。我想使用优先邮箱,但stash() 和unstash() 还不能使用优先邮箱。有没有办法只使用优先邮箱来做到这一点?
如果我有序列 M1-M2-M3-Stop-M4-Start-M5(并在打印 M1 时停止接收),我应该得到第一个打印“M1”和第二个“M2-M3-M4” -M5"(所以旧的 M2 和 M3 必须在新的 M4 之前打印)。 Stash() 和 unstash() 不适用于优先邮箱,所以我的想法是创建具有最高优先级的启动/停止消息、M1、M2 等...具有最低优先级的消息,在我使用 become() 之后,我虽然ActorB 可以再次发送保存的消息,但这次具有中等优先级(因此它们将在新消息之前被读取,但在停止消息之后)。是否可以?有没有更好的解决方案?
【问题讨论】:
-
这种情况永远不会发生在您在此场景中描述的发送者-接收者对中。 Akka 明确保证这一点:doc.akka.io/docs/akka/snapshot/general/…
-
所以如果我有一个优先邮箱,即使它们具有相同的优先级,邮件的顺序可能会改变?
-
实际上,我误解了您的帖子,似乎优先邮箱可以完成您的建议。如果 stash 和 unstash 不起作用,您可以使用队列。