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
object
s instead. - If you have a class without a parameter list, you can omit the parenthesis
Actor
'sreceive
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.
精彩评论