开发者

akka how to to launch a master task and block on it finishing?

开发者 https://www.devze.com 2023-03-05 22:46 出处:网络
I\'m trying to get started with akka in scala. In the main scala thread I\'d like to start an akka actor, send one message to it, and block until that actor terminates. What is the best way to do this

I'm trying to get started with akka in scala. In the main scala thread I'd like to start an akka actor, send one message to it, and block until that actor terminates. What is the best way to do this?

For example I have a test actor that just repeatedly sends messages to itself:

class Incrementer() extends Actor {

  val maxMessages = 5
  var counter = 0

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

and it is invoked via:

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

That block takes just over 5,000 ms to execute instead of what I expect to be a few ms, so it seems to have to do with a default future timeout - and the program does not actually terminate. All I'm really trying to do is 开发者_运维技巧time the performance of sending x number of messages. What's going on here?


As Viktor mentioned, in order for !! to terminate successfully, you have to reply to the message. The 5 second delay you are seeing the actor's default timeout, which is configurable. More info can be found on the Akka site.

If you use forward to send the message instead of !, then self.reply will respond to the original sender.

The first message you send to an Akka actor performs some setup that doesn't happen when processing other messages. Be sure to take that into account for your timings.

Corrected code would be:

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()
      }
  }
}

Aside: I made a few other changes to get your code in line with idiomatic Scala. Your code works without these changes, but it now looks like more typical Scala code.

  • Case classes without parameter lists have been deprecated. Use objects instead.
  • If you have a class without a parameter list, you can omit the parenthesis
  • Actor's receive method does not have parens; your implementing class shouldn't have them either.
  • It's purely a matter of style, but the body of a case statement does not require braces.
0

精彩评论

暂无评论...
验证码 换一张
取 消