Scala Actors
Scala Actors
Scala Actors
Transform your PDFs into Flipbooks and boost your revenue!
Leverage SEO-optimized Flipbooks, powerful backlinks, and multimedia content to professionally showcase your products and significantly increase your reach.
<strong>Scala</strong> <strong>Actors</strong> <br />
Concurrency is an important topic in computer science. Advances in computer <br />
architecture continue to push for greater levels of thread-‐level parallelism. Moving <br />
forward, computer languages must be able to efficiently and effectively implement <br />
concurrency to remain viable. <br />
Traditionally, concurrency can be handled using task-‐based threads or event-‐based <br />
threads. Task-‐based threading, as used by java, involves defining a ‘task’ to run as a <br />
thread. To run a task-‐based thread, a new thread is created and started to complete <br />
the task and can then run in parallel to any other processing. When the thread has <br />
completed its task, it is discarded. <br />
Alternatively, <strong>Scala</strong> implements concurrency using event-‐based actors. The name <br />
actor can is telling of what an actor does. In performing arts, an actor is an <br />
individual that has a role to perform and they can communicate with other actors by <br />
communicating. Similarly, actors in <strong>Scala</strong> are objects that run concurrent processes <br />
and can send and receive messages from other actors. Messages passed to an actor <br />
are queue in the actor’s mailbox. Typically, an actor will perform pattern matching <br />
on the message to determine what actions to take on the message. <br />
The actor paradigm is considered to be easy to understand for the developer. <br />
Additionally, the functional programming that is available to the <strong>Scala</strong> programmer <br />
can improve the code design for concurrency by minimizing mutable state. <br />
An example <br />
Consider the following example. A familiar game played by kids is Marco Polo. In <br />
this game, a player will call out “Marco”, to which a second player must respond <br />
“Polo”. We can recreate this behavior using <strong>Scala</strong> and actors. <br />
To be able to use actors, the following <strong>Scala</strong> libraries must be imported into the <br />
application. <br />
import scala.actors._<br />
import scala.actors.Actor._<br />
The package scala.actors includes the trait Actor that can be extend to create the <br />
actor objects as well as all other classes, objects and traits related to actors. The <br />
package scala.actors.Actor has methods that are used by the actor objects. <br />
Next, define singleton objects to act as messages. These objects are declared to be <br />
case objects as the receiving actor will use pattern matching to determine the action <br />
to take. <br />
<br />
1
case object Marco<br />
case object Polo<br />
case object Stop<br />
Next, define the behavior of the player1 object with the class ‘Marco’. <br />
class Marco(count: Int, player2: Actor) extends Actor {<br />
def act() {<br />
var tries = count - 1<br />
player2 ! Marco<br />
println("Marco...")<br />
while (true) {<br />
receive {<br />
case Polo => {<br />
if (tries > 1) {<br />
println("Marco...")<br />
player2 ! Marco<br />
tries -= 1<br />
} else {<br />
player2 ! Stop<br />
exit()<br />
}<br />
}<br />
}<br />
}<br />
}<br />
}<br />
The <strong>Actors</strong> ‘act’ method is used to define the behavior of the Actor. A variable ‘tries’ <br />
is defined to limit the number of messages sent. Player1 initiates the game by <br />
sending player2 the message ‘Marco’. In <strong>Scala</strong>, messages are sent to actors using the <br />
‘!’ operator. Next, player1 continuously waits for the return ‘Polo’ message using the <br />
‘receive’ method and pattern matching. Upon receiving the ‘Polo’ message, player1 <br />
will again send the ‘Marco’ message to player2 if the maximum number of tries has <br />
not been reached. Once the number of tries has been reached, the actor exits. <br />
Next, the behavior of player2 is defined with the class ‘Polo’. <br />
class Polo extends Actor {<br />
def act() {<br />
while (true) {<br />
receive {<br />
<br />
2
case Marco => {<br />
println("Polo...")<br />
sender ! Polo<br />
}<br />
case Stop => {<br />
exit()<br />
}<br />
}<br />
}<br />
}<br />
}<br />
The player2 object, implementing the ‘Polo’ class, waits in a loop to receive the <br />
‘Marco’ message from player 1. Every time the actor receives the ‘Marco’ message, it <br />
returns the ‘Polo’ message. Notice that the ‘Polo’ message is sent to the ‘sender’ as <br />
opposed to explicitly sending the message player1. Sender refers to the actor that <br />
sent the last received message. <br />
Lastly, an object is defined that creates instances of the classes we created and starts <br />
the actors. <br />
object marcopolo extends Application {<br />
val player2 = new Polo()<br />
val player1 = new Marco(10, player2)<br />
player1.start()<br />
player2.start()<br />
}<br />
The following is the output of the compiling and running the previously described <br />
function: <br />
$ scalac marcopolo.scala<br />
$ scala marcopolo<br />
Polo...<br />
Marco...<br />
Polo...<br />
Marco...<br />
Polo...<br />
Marco...<br />
Polo...<br />
Marco...<br />
Polo...<br />
<br />
3
Marco...<br />
Polo...<br />
Marco...<br />
Polo...<br />
Marco...<br />
Polo...<br />
Marco...<br />
Polo...<br />
act() method vs. actor{} function <br />
In the previous example, we defined an actor’s ‘act’ method to define the behavior of <br />
the actor. However, there is a second method to create an actor without creating a <br />
class using the ‘actor’ function. For example, the ‘player2’ could be redefined to the <br />
following: <br />
val player2: Actor = actor {<br />
while (true) {<br />
receieve {<br />
case Marco => {<br />
println("Polo...")<br />
sender ! Polo<br />
}<br />
case Stop => {<br />
exit()<br />
}<br />
}<br />
}<br />
}<br />
Here, the player2 actor is defined inline as opposed to instantiating an Actor class. It <br />
is important to note that using this method, it is no longer necessary to class the <br />
‘start’ method of the actor object. The actor is started immediately. <br />
receive{} function vs. react{} function <br />
In the previous example, we waited to for a message to return using the ‘receive’ <br />
function. The ‘receive’ function is a blocking function, meaning that the thread that <br />
is currently executing the thread will be blocked until the message is received. <br />
Using the receive message preserves the call stack. <br />
<br />
4
In <strong>Scala</strong>, actors are executed on a thread pool that initially has 4 worker threads. <br />
When the number of blocking threads increases, the size of the thread pool grows to <br />
match. However, in situations with a large number of actors, it may be desirable to <br />
avoid this blocking behavior. <br />
<strong>Scala</strong> has a second method to return a message: the ‘react’ function. As opposed to <br />
the ‘receive’ function, the ‘react’ function is non-‐blocking. Instead of waiting for the <br />
message to return, ‘react’ creates a closure. When the react function receives a <br />
value, an available thread begins execution the actor. Take note, however, that the <br />
react function cannot be used inside a while loop. As a result, <strong>Scala</strong> includes a ‘loop’ <br />
function to that behaves as an infinite loop and ‘loopWhile’ that behaves in a similar <br />
manner to a while loop. Using the ‘react’ function instead of the ‘receive’ function <br />
could be written as follows: <br />
class Polo extends Actor {<br />
def act() {<br />
loop {<br />
react {<br />
case Marco => {<br />
println("Polo...")<br />
sender ! Polo<br />
}<br />
case Stop => {<br />
exit()<br />
}<br />
}<br />
}<br />
}<br />
}<br />
In addition to the ‘react’ and ‘receive’ functions, <strong>Scala</strong> also includes ‘reactWithin’ and <br />
‘receiveWithin’ functions. These functions work in the same way as the <br />
corresponding ‘react’ and ‘receive’ functions but allow the programmer to specify a <br />
timeout. <br />
!, !!, and !? <br />
In the previous example, messages were sent using the ‘!’ operator. <strong>Scala</strong> also <br />
provides the ‘!?’ operator which will create a synchronous message. Instead of <br />
returning like an asynchronous message, this operator waits for a reply. For <br />
example the following code: <br />
var response = player1 !? Polo<br />
<br />
5
This code will send the Polo message to the object player1 and wait for a response, <br />
which it will assign to the variable ‘response’. <br />
Additionally, <strong>Scala</strong> has the ‘!!’ operator, which returns immediately. However, since <br />
a message has not been received back, the operator returns a future instead. A <br />
future is a representation of the response that allows to the caller to await the reply. <br />
In this case, the blocking will occur only when trying to access the future. <br />
This tutorial has presented a brief introduction to <strong>Scala</strong> actors. These concepts can <br />
be extended to create far more complex and interesting code. The <strong>Scala</strong> distribution <br />
includes a several examples of the use of <strong>Scala</strong> actors. These are available at /doc/scala-‐devel-‐docs/examples/actors/. <br />
<br />
6
References <br />
Tate, Bruce A. Seven Languages in Seven Weeks: A Pragmatic Guide to Learning <br />
Programming Languages. Pragmatic Programmers, 2010. <br />
<strong>Actors</strong>: A Short Tutorial. http://www.scala-‐lang.org/node/242 <br />
<strong>Scala</strong> Standard Library 2.8.1 Final. http://www.scala-‐lang.org/api/current/ <br />
index.html <br />
Haller, Philipp and Martin Odersky. “<strong>Actors</strong> that Unify Threads and Events”. Lecture <br />
Notes in Computer Science. Vol 4467, pp 171-‐190, 2007. <br />
<br />
7