3

我正在尝试在scala中开始使用akka。在主 scala 线程中,我想启动一个 akka 演员,向它发送一条消息,然后阻塞直到该演员终止。做这个的最好方式是什么?

例如,我有一个测试参与者,它只是反复向自己发送消息:

class Incrementer() extends Actor {

  val maxMessages = 5
  var counter = 0

  def receive() = {
    case DoIncr() => {
      if (counter < maxMessages) {
        counter += 1
        self ! DoIncr()
      } else {
        self.stop()
      }
    }
  }
}

它通过以下方式调用:

val inc = actorOf(new Incrementer()).start()
val result = inc !! DoIncr()
println(result) // this should block this thread, but it doesn't seem to.

// do other stuff

该块的执行时间刚刚超过 5,000 毫秒,而不是我预期的几毫秒,因此它似乎与默认的未来超时有关 - 并且程序实际上并没有终止。我真正想做的只是计算发送 x 条消息的性能。这里发生了什么?

4

1 回答 1

4

正如 Viktor 所说,为了!!成功终止,您必须回复消息。您看到的演员默认超时的 5 秒延迟,这是可配置的。更多信息可以在Akka 网站上找到。

如果您使用forward发送消息而不是!self.reply则将回复原始发件人。

您发送给 Akka Actor 的第一条消息会执行一些在处理其他消息时不会发生的设置。一定要考虑到你的时间安排。

更正后的代码是:

import akka.actor._

object DoIncr

class Incrementer extends Actor {
  val maxMessages = 5
  var counter = 0

  def receive = {
    case DoIncr =>
      if (counter < maxMessages) {
        counter += 1
        self forward DoIncr
      } else {
        self.reply(()) // replying with () since we have nothing better to say
        self.stop()
      }
  }
}

旁白:我做了一些其他更改以使您的代码与惯用的 Scala 保持一致。您的代码无需这些更改即可工作,但现在看起来更像是更典型的 Scala 代码。

  • 不推荐使用没有参数列表的案例类。请改用objects。
  • 如果你有一个没有参数列表的类,你可以省略括号
  • Actorreceive方法没有括号;你的实现类也不应该有它们。
  • 这纯粹是风格问题,但case语句的主体不需要大括号。
于 2011-05-18T06:22:19.767 回答