Creating Actors

You typically create objects and invoke methods on them. An actor is also an object, but you never call methods on it directly. Instead you send messages and each actor is backed by a message queue. If an actor is busy processing a message, then the messages that arrive are queued—the senders aren’t blocked; they fire-and-forget. At most, one message is processed on an actor at any given time. Actors are born and built with thread safety.

Let’s define an actor.

ProgrammingActors/HollywoodActor.scala
 
import​ akka.actor._
 
 
class​ HollywoodActor() ​extends​ Actor {
 
def​ receive = {
 
case​ message => println(s​"playing the role of $message"​)
 
}
 
}

Scala uses actors from Akka—a very powerful reactive library written in Scala. To create an actor, extend from the Actor trait and implement the receive method. The body of the receive method looks familiar; it’s the pattern matching syntax minus the call to match. The match is happening on an implicit message object. The body of the method is a partially applied function.

In this example, we simply print the message received; we’ll soon bring more logic into the actor. Let’s use the actor we just defined.

ProgrammingActors/CreateActors.scala
 
import​ akka.actor._
 
 
object​ CreateActors ​extends​ App {
 
val​ system = ActorSystem(​"sample"​)
 
 
val​ depp = system.actorOf(Props[HollywoodActor])
 
 
depp ! ​"Wonka"
 
 
system.shutdown()
 
}

Akka actors are hosted within an ActorSystem, which manages threads, message queues, and actor lifetime. Instead of using the traditional new to create an instance, we used a special actorOf factory method to create the actor and assigned it to the reference named depp. Also, instead of the usual method call syntax, we pass a message to the actor “Wonka”—a mere string in this example—using the method named !. Instead of using the ! method, you could use a method named tell, but that would require passing an additional parameter of sender. Also you wouldn’t look as cool if you use a method name that’s intuitive to the reader. Talking about being intuitive, they should’ve really called it action.

The actor system manages a pool of threads that stay active as long as the system is active. For the program to terminate when the main code completes, we have to tell the actor system to shutdown—that is, exit its threads.

To compile the code, enter the following command:

 
scalac -d classes HollywoodActor.scala CreateActors.scala

The Scala installation has the Akka actors library bundled; we don’t have to include anything in the classpath to compile the code. Likewise, we don’t need to include any additional libraries to run. Here’s the command:

 
scala -classpath classes CreateActors

Let’s take a look at the output:

 
playing the role of Wonka

We didn’t write a lot of code, but still, that’s a boring output. So much went on in that code, but the details were totally lost in that output. Let’s change the code to gain a better insight.

Let’s modify the body of the receive method:

 
case​ message => println(s​"$message - ${Thread.currentThread}"​)

When a message is received, we print that along with the details of the executing thread. Let’s change the calling code to send multiple messages to multiple actors:

 
val​ depp = system.actorOf(Props[HollywoodActor])
 
val​ hanks = system.actorOf(Props[HollywoodActor])
 
 
depp ! ​"Wonka"
 
hanks ! ​"Gump"
 
 
depp ! ​"Sparrow"
 
hanks ! ​"Phillips"
 
println(s​"Calling from ${Thread.currentThread}"​)

This should give us some more interesting details to look at. Let’s run and take a look at the output:

 
Wonka - Thread[sample-akka.actor.default-dispatcher-2,5,main]
 
Gump - Thread[sample-akka.actor.default-dispatcher-3,5,main]
 
Calling from Thread[main,5,main]
 
Phillips - Thread[sample-akka.actor.default-dispatcher-3,5,main]
 
Sparrow - Thread[sample-akka.actor.default-dispatcher-2,5,main]

We sent two messages to each of the actors: “Wonka” and “Sparrow” to the actor depp, and “Gump” and “Phillips” to the actor hanks. The output shows a number of interesting details:

  • A pool of thread was made available to us without any fuss.

  • The actors run in a different thread than the calling code’s main thread.

  • Each actor processes only one message at a time.

  • The actors run concurrently, processing messages at the same time.

  • The actors are asynchronous.

  • The caller did not block—the main did not wait to run the println until after the actors responded.

Even though we have a lot more ground to cover, you can already see the benefits of this approach. They come from what we did not do. We didn’t explicitly create a pool of threads. Nor did we explicitly schedule tasks. Had we used the JDK concurrency library, we’d have used executors and calls to methods like submit—we were saved from writing a lot of code. Instead we simply sent a message to the actor and the actor system took care of the rest. That’s pretty cool, eh?

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.58.197.26