首页 文章

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

提问于
浏览
3

我正试图在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 回答

  • 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 .

    • 如果您的类没有参数列表,则可以省略括号

    • Actorreceive 方法没有parens;你的实现类也不应该有它们 .

    • 这纯粹是一种风格问题,但 case 语句的主体不需要括号 .

相关问题