演员可以在特定条件下阅读消息吗?

时间:2015-08-28 14:35:57

标签: scala concurrency akka actor messages

我遇到这种情况:

  • ActorA每30-40秒发送一次ActorB开始/停止消息
  • ActorA发送ActorB字符串以打印(总是)
  • ActorB必须打印他收到的字符串,但前提是ActorA只发送了一条开始消息

现在我想知道我是否可以做以下事情:

  • ActorB是否只能在特定条件下读取消息(如果布尔值设置为true)而不丢失接收到的消息,而该布尔值设置为false?
  • 在其他字符串消息之前,ActorB可以从ActorA读取开始/停止消息吗?我想有这种情况:ActorA向ActorB发送一条开始消息,ActorB开始打印他在开始消息之前收到的字符串(并且仍在接收)然后在收到停止消息后立即停止?

我不知道我是否解释得很好。

编辑:谢谢,答案很好,但我仍然有些疑惑。

  • 是否会成为消息的顺序?我的意思是,如果我有“Start-M1-M2-Stop-M3-M4-M5-Start-M6-M7-Stop”,打印顺序是“M1-M2”还是“M3-M4-M5-M6” -M7“或者可以在M3,M4和M5之前读取M6(如果在变为刚刚接收到M6之后)?

  • 我可以为启动/停止消息提供更高的优先级吗?如果ActorB收到“M1-M2-M3”,然后在打印“M1”时收到停止信息,我希望ActorB再次保存M2和M3。

5 个答案:

答案 0 :(得分:2)

检查Become/Unbecome功能。它可以让你改变演员的行为。

如果我理解正确,你希望你的ActorB有两种不同的状态。在第一个状态中,它应该缓存它收到的消息。在第二种状态下,它应该打印所有缓存的消息并开始打印所有新消息。

这样的事情:

case class Start
case class Stop
case class Message(val: String)

class ActorB extends Actor {

  var cache = Queue()

  def initial: Receive = {
    case Message(msg) => cache += msg
    case Start => 
      for (m <- cache) self ! Message(m)
      context.become(printing)
  }

  def printing: Receive = {
    case Message(msg) => println(msg)
    case Stop => context.become(initial) //or stop the actor
  }

  def receive = initial
}

答案 1 :(得分:2)

您可以使用http-server /path/特征和Akka的Stash功能完全解决您的问题。这个想法如下:

当您收到become/unbecome消息时,您会切换到隐藏所有非Stop消息的行为。当您收到Start消息时,您会切换到打印所有收到的消息的行为,此外您还会解冻同时到达的所有消息。

Start

答案 2 :(得分:0)

让演员B在两种状态(两种不同的行为)之间交替。在最初的&#39;待定&#39;国家,它等待开始&#39;消息,同时stashing任何其他消息。

收到“开始&#39;消息,解冻所有存储的消息,并become&#39;激活&#39;等待“停止”消息消息并写出收到的其他消息(包括未安装的消息)。在收到“停止”后消息,还原为&#39;待定&#39;行为。

答案 3 :(得分:0)

我的一些想法

  1. 是的,如果boolean标志来自某个系统资源,如db或配置文件,但我不认为它应该依赖于任何外部消息,因为actor接收来自多个其他actor的消息。如果ActorB仅由ActorA使用,则两者可以合并为一个

  2. 类似于1,如何处理来自多个演员的消息?如果只有一个actorA,则可以合并两个actor。如果有多个,则可以在数据库中设置标志,actorA将db中的标志更改为“Start”或“Stop”。和Actor B将打印或不打印标志。

  3. 演员应该在其他演员的状态下非常独立地做某事。启动和停止实际上是ActorA的一些状态而不是ActorB

答案 4 :(得分:0)

你已经有了很多好的答案,但不知怎的,我觉得有必要提供更简短的内容,因为你需要的不一定是状态机:

SELECT 
    `user`.`id`,
    `user`.`name`,
    `stats`.*
FROM 
`#__users` `user`
LEFT JOIN 
    (SELECT 
        `_s`.`userId`,
        SUM(`_s`.`fild12`) AS `fild12`,
        SUM(`_s`.`fild13`) AS `fild13`
     FROM 
        `#__logbookEventdata` `_s`
     GROUP BY `_s`.`userId`) `stats`
ON 
    (`stats`.`userId`=`user`.`id`)