演员构造函数Args与路由器

时间:2014-01-28 14:46:35

标签: akka

我正在尝试创建一个路由器,它将使用构造函数arg部署actor,这是一种变异方法。

object LocalRouterArgEvalFrequency {
  def main(args: Array[String]) {
    val system = ActorSystem("TestSystem")
    var number = 0

    def getANumber: Int = {
      number += 1
      number
    }

    val router = system.actorOf(Props(classOf[Foo], getANumber)
                               .withRouter(RoundRobinRouter(5)), "RRRouter")
    (1 to 10).foreach(_ => router ! "What's Your Number?")
  }
}

class Foo(number: Int) extends Actor {
  println("I got instantiated")
  def receive: Actor.Receive = {
    case msg: String => println(s"My Number is $number")
  }
}

我希望在这些行中看到一些东西作为输出(我认为RoundRobin是我最后检查的最好的努力所以没有保证):

I got instantiated
I got instantiated
I got instantiated
I got instantiated
I got instantiated
My Number is 1
My Number is 2
My Number is 3
My Number is 4
My Number is 5
My Number is 1
My Number is 2
My Number is 3
My Number is 4
My Number is 5

相反,我看到以下内容:

I got instantiated
I got instantiated
I got instantiated
I got instantiated
I got instantiated
My Number is 1
My Number is 1
My Number is 1
My Number is 1
My Number is 1
My Number is 1
My Number is 1
My Number is 1
My Number is 1
My Number is 1

我认识到注入这样的突变很可能不是一个好主意模式,但我在测试代码中有一个与这种类型的交互非常相似的用例。

有没有办法让Props每次使用路由器部署进行评估?或者也许有一种不同的方式去做,我没有看到......提前谢谢!

1 个答案:

答案 0 :(得分:3)

要记住的一件事是使用当前方法捕获构造函数arg值一次。换句话说,getANumber实际上只被调用一次,其结果(在本例中为1)被用作路由器创建的所有actor的构造函数arg。如果您希望每个人都有一个唯一的号码,那么您可以尝试这样的事情:

object LocalRouterArgEvalFrequency {
  def main(args: Array[String]) {
    val system = ActorSystem("TestSystem")
    var number = 0

    def getANumber: Int = {
      number += 1
      number
    }
    val routees = List.fill(5)(getANumber).map(i => system.actorOf(Props(classOf[Foo], i)))
    val router = system.actorOf(Props.empty.withRouter(RoundRobinRouter(routees = routees)), "RRRouter")
    (1 to 10).foreach(_ => router ! "What's Your Number?")
  }
}

class Foo(number: Int) extends Actor {
  println("I got instantiated: " + number)
  def receive: Actor.Receive = {
    case msg: String => println(s"My Number is $number")
  }
}

修改

您还可以使用Props.apply的其他变体创建路由器,如下所示:

val router = system.actorOf(Props(new Foo(getANumber)).withRouter(RoundRobinRouter(5)), "RRRouter")

这种方法可能更符合您的要求。