Parallel

JVM Concurrency and Actors with GPars

By Vaclav Pech, April 25, 2011

The GPars project makes concurrency easily accessible and safe to use on the JVM

Continuations

A stateful actor's code is processed in chunks, separated by quiet periods of waiting for new events (messages). This can be naturally modeled through continuations. However, since JVM doesn't support continuations directly, they have to be simulated in the actor frameworks, which has a slight impact on organization of the actors' code.

Calling the react() method from within the actor's code has slightly different semantics than just reading the next message from the actor's inbox. Under the covers, the closure supplied as a parameter to the react method is scheduled for processing once a message becomes available. The scheduling is the last work the current thread does on the actor's behalf. Once scheduled, the thread is detached from the actor and returned to the pool to serve other actors.

To allow detaching actors from the threads, the react() method requires that the code to be written in a special "Continuation-style."

Essentially, react() schedules the supplied code (closure) to be executed upon next message arrival and quits the actor body. The closure supplied to the react() methods is the code where the computation should continue. Thus, we have continuation style.

Stateful Actors Used from Java

You may see that stateful actors use nested closures heavilly to organize their bodies. Although it is possible to encode a nested actor's body in Java using anonymous inner classes for react's parameters, sticking to Groovy can save you a lot of typing and considerably reduce verbosity of the code.

Active Objects

Active objects give actors an OO facade, allowing you to program in a more traditional OO style. You avoid dealing directly with the actor machinery, sending messages, defining message handlers and sending or waiting for replies.

As you can see in the code example above, active objects are plain POGOs (Plain Old Groovy Objects) annotated with the @ActiveObject annotation. Where they differ from ordinary objects is their behavior upon method invocation. Leveraging Groovy compile-time code transformations, whenever any of the active methods (marked as @ActiveMethod) are called, GPars translates the method calls to messages being sent to the object's internal actor. The internal (hidden) actor then handles these messages asynchronously by invoking the desired functionality in its own context.

Because the code now runs asynchronously and doesn't block the caller, we need a new way to propagate the return values up to the caller. The mechanism is commonly referred to as "Future" or "Promise." Active methods return such Promises instead of real results, which by themselves are only handles allowing the caller to obtain the result once it is calculated. The part1, part2 and part3 variables in the preceding code example above are these "Promises." The script calls their get() method to retrieve the return value.

Because this mechanism relies on compile-time meta-programming, active objects must be implemented in Groovy. However, once created they can be invoked from Java just like from Groovy.

Summary

GPars brings together several handy concurrency abstractions. This article was dedicated to the actors concept, which is (along with Communicating Sequential Processes (CSP) and dataflow) one of the popular message-passing paradigms. We have seen how actors are created and invoked both in Groovy and in Java and how active objects can be used to give actors a familiar OO face.

GPars toolset

Because there is no single answer to all the concurrency challenges, GPars provides more than just actors, It includes:

Agents

Dataflow concurrency

Communicating Sequential Processes

Parallel collections

Fork/Join capabilities

Composable asynchronous functions

This wide range of operations enables developers to pick the best tool for their job. Going into details of each of these abstractions is, however, beyond the scope of this article. The best way to see GPars in its entirety is to check out the GPars User Guide.

Václav is a programming enthusiast who's constantly seeking ways to make development more effective and enjoyable. He's particularly interested in server-side Java technologies, distributed systems and concurrency. You can check out his blog or follow him on twitter.

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task.
However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

Video

This month's Dr. Dobb's Journal

This month,
Dr. Dobb's Journal is devoted to mobile programming. We introduce you to Apple's new Swift programming language, discuss the perils of being the third-most-popular mobile platform, revisit SQLite on Android
, and much more!