Sunday, April 26, 2015

Concurrency with Scala Actors and Akka

Now, I could kick this off by talking about Scala and it's immutability, statelessness, object-orientedness and functional programming, etc. but there are tons of resources for that, so I won't waste your time. I will, however, talk about concurrency through the Actor model[1], which have been making a bit of a resurgence in the last few years with the reactive programming[2] slowly becoming as popular as object oriented programming, itself. This is going to be a hands on learning approach, with some mention of concurrency fashioned by other systems.

The following diagram represents the Actor system, which is entirely based on passing messages between actors.

Prerequisites: You'll want to install Scala and SBT. This guide was written for Mac OS X users.

An Akka Actor

Let's start by cloning the roblayton/scala-actors-example repository. Run git clone https://github.com/roblayton/scala-actors-example.git from the command line and take a look at the code in HelloActor.scala:

package com.roblayton.example

import akka.actor.Actor

class HelloActor extends Actor {
  def receive = {
    case "hello" => println("hello to you as well")
    case "how are you?" => println("doing fine")
    case _ => println("message not recognized")
  }
}

This actor has one job- respond to messages matched by the receive method by printing lines to the console. While the program is running, this actor will occupy one thread, doing nothing until a message is received. Both Scala actors and Akka actors have the same fundamental traits, since they're based on the Actor model, which have the ability to receive and react to messages according to their context, send messages to other actors, and create new actors. The Actor model also provides certain guarantees:

  • Any actor will only handle a single message at a time
  • An actor's internal state can only be mutated from the receive function
  • Messages sent by actor A to actor B will arrive in the order they were transmitted

Instantiating Our Actors

Now, we'll be sending messages from our program's main entry point. You'll find code that instantiate two types of actors, but we're only concerned with HelloActor, at the moment. This will involve the following lines of code within Main.scala:

var system = ActorSystem("HelloSystem")

var helloActor = system.actorOf(Props[HelloActor], name = "helloactor")

We start by instantiating our ActorSystem and make a call to actorOf which returns an instance of ActorRef, providing you with the ability to interact with the Actor. The ActorRef is immutable and can be serialized and used on a remote host, maintaining its one to one relationship with the Actor on the original node across the network[3]. Notice we're also instantiating an Actor that can accept parameters, using slightly different syntax to instantiate the second Actor, HelloActorWithArgs.scala:

var helloActorWithArgs = system.actorOf(Props(new HelloActorWithArgs("Rob")), name = "helloactorwithargs")

Sending Messages to Our Actors

Sending messages to our Actors can now be done with the following syntax:

helloActor ! "hello"
helloActor ! "how are you?"
helloActor ! "goodbye"
...
helloActorWithArgs ! "what's your name?"
helloActorWithArgs ! "goodbye"
Run sbt run from the root directory in your terminal and you will see the following output, which shows our messages being handled in parallel:

[info] Running com.roblayton.example.Main
hello to you as well
my name is Rob
doing fine
message not recognized
message not recognized

Ping Pong

To demonstrate an example of Actors communicating between each other, please clone and run my scala-pingpong-example:

git clone https://github.com/roblayton/scala-pingpong-example.git

cd scala-pingpong-example
sbt run

Notice how we're also instantiating both Actors up front, but we're passing the ActorRef along, allowing one of the Actors to pass messages to the other:

var system = ActorSystem("PingPongSystem")
val pong = system.actorOf(Props[PongActor], name="pong")
var ping = system.actorOf(Props(new PingActor(20, pong)), name = "ping")

References:


1. ^ Wikipedia (17 June 2015). "The Actor Model"
2. ^ Bonér, Jonas; Farley, Dave; Kuhn, Roland; Thompson, Martin (16 September 2014). "The Reactive Manifesto"
3. ^ Akka Docs v2.0 (06 March 2012). "Actors (Scala)"

No comments:

Post a Comment