akka如何启动一个主任务并阻止它完成?

时间:2011-05-16 03:19:59

标签: scala akka

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

例如,我有一个测试演员只是反复向自己发送消息:

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条消息的时间。这是怎么回事?

1 个答案:

答案 0 :(得分:4)

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

如果您使用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代码。

  • 不推荐使用不带参数列表的案例类。请改用object
  • 如果您的班级没有参数列表,则可以省略括号
  • Actor的{​​{1}}方法没有parens;你的实施班也不应该有它们。
  • 这纯粹是一种风格问题,但receive语句的正文不需要大括号。