Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple concurrency with an Akka Hello World sample

Tags:

scala

akka

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.

like image 888
matthewrk Avatar asked Nov 29 '13 18:11

matthewrk


People also ask

How does Akka handle concurrency?

Akka's approach to handling concurrency is based on the Actor Model. In an actor-based system, everything is an actor, in much the same way that everything is an object in object-oriented design.

Is Akka single-threaded?

The key abstraction in Akka is the Actor, which provides behavior and can store state. In Akka, actors are guaranteed to be run in a single-threaded illusion, which means that the Akka framework takes care of threading issues while allowing us to focus on the behavior that needs to be implemented.

Is Akka a good framework?

Akka is a truly reactive framework because everything in the sense of sending and receiving a message to Actors, is lock-less, non-blocking IO, and asynchronous.

What is alternative to Akka?

Spring, Scala, Erlang, Kafka, and Spring Boot are the most popular alternatives and competitors to Akka.


2 Answers

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.

like image 103
sourcedelica Avatar answered Sep 30 '22 16:09

sourcedelica


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

like image 41
cmbaxter Avatar answered Sep 30 '22 14:09

cmbaxter