Reputation: 687
I'm evaluating Akka for a distributed service layer, the following example prints Hello {n} 10 times, but does it one after the other. As I understand it this is intentional for an Akka actor, so where do I go from here to make it concurrent?
import akka.actor._
object HelloActor {
case class SayHello(message: String)
}
class HelloActor extends Actor {
def receive = {
case HelloActor.SayHello(message) =>
Thread.sleep(1000)
println(message)
}
}
object Main extends App {
val system = ActorSystem("ActorSystem")
val hello = system.actorOf(Props[HelloActor])
for (i <- 1 to 10) {
hello ! HelloActor.SayHello(s"Hello $i")
}
}
I've experimented with creating multiple actors from the Main class but that feels wrong somehow, shouldn't I just call the actor then it handles concurrency / spawning more actors on its own? Could anyone provide an example of this (preferably modifying the above code). I've been reading and reading but it feels like a lot to take in immediately and I feel I'm just missing a key concept here somewhere.
Upvotes: 6
Views: 2514
Reputation: 24040
For your use case you'll probably want to use Routers.
For example:
val hello = system.actorOf(Props[HelloActor].withRouter(
RoundRobinRouter(nrOfInstances = 10)))
hello ! HelloActor.SayHello("Hello!") // Sends to one of the 10
As a side note, you should avoid blocking (ie. Thread.sleep
) in your actor's receive
method.
Upvotes: 4
Reputation: 35443
As @sourcedelica mentioned in the comments, routing is probably what you want to do. A simple refactor to your example using a RoundRobinRouter
could look like this:
import akka.actor._
import akka.routing._
object HelloActor {
case class SayHello
}
class HelloActor extends Actor {
def receive = {
case HelloActor.SayHello =>
println(s"saying hello from: ${self.path}")
}
}
object Main extends App {
val system = ActorSystem("ActorSystem")
val hello = system.actorOf(Props[HelloActor].withRouter(RoundRobinRouter(10)))
for (i <- 1 to 10) {
hello ! HelloActor.SayHello
}
}
This is a pretty simple example as it's using a simple router (round robin) and it's non-resizing. You can do a lot more with the routers and I highly suggest reading up on them more at:
http://doc.akka.io/docs/akka/2.2.3/scala/routing.html
Upvotes: 1