Click here to close now.

Welcome!

Java Authors: Liz McMillan, VictorOps Blog, Esmeralda Swartz, Pat Romanski, Jason Bloomberg

Related Topics: Java

Java: Article

Next-Gen Concurrency in Java: The Actor Model

Multiple concurrent processes can communicate with each other without needing to use shared state variables

At a time where the clock speeds of processors have been stable over the past couple of years, and Moore's Law is instead being applied by increasing the number of processor cores, it is getting more important for applications to use concurrent processing to reduce run/response times, as the time slicing routine via increased clock speed will no longer be available to bail out slow running programs.

Carl Hewitt proposed the Actor Model in 1973 as a way to implement unbounded nondeterminism in concurrent processing. In many ways this model was influenced by the packet switching mechanism, for example, no synchronous handshake between sender and receiver, inherently concurrent message passing, messages may not arrive in the order they were sent, addresses are stored in messages, etc.

The main difference between this model and most other parallel processing systems is that it uses message passing instead of shared variables for communication between concurrent processes. Using shared memory to communicate between concurrent processes requires the application of some form of locking mechanism to coordinate between threads, which may give rise to live locks, deadlocks, race conditions and starvation.

Actors are the location transparent primitives that form the basis of the actor model. Each actor is associated with a mailbox (which is a queue with multiple producers and a single consumer) where it receives and buffers messages, and a behavior that is executed as a reaction to a message received. The messages are immutable and may be passed between actors synchronously or asynchronously depending on the type of operation being invoked. In response to a message that it receives, an actor can make local decisions, create more actors, send more messages, and designate how to respond to the next message received. Actors never share state and thus don't need to compete for locks for access to shared data.

The actor model first rose to fame in the language Erlang, designed by Ericcson in 1986. It has since been implemented in many next-generation languages on the JVM such as Scala, Groovy and Fantom. It is the simplicity of usage provided via a higher level of abstraction that makes the actor model easier to implement and reason about.

It's now possible to implement the actor model in Java, thanks to the growing number of third-party concurrency libraries advertising this feature. Akka is one such library, written in Scala, that uses the Actor model to simplify writing fault-tolerant, highly scalable applications in both Java and Scala.

Implementation
Using Akka, we shall attempt to create a concurrent processing system for loan request processing in a bank as can be seen in the Figure 1.

Figure 1

The system consists of four actors:

  1. The front desk - which shall receive loan requests from the customers and send them to the back office for processing. It shall also maintain the statistics of the number of loans accepted/rejected and print a report detailing the same on being asked to do so.
  2. The back office - which shall sort the loan requests into personal loans and home loans, and send them to the corresponding accountant for approval/rejection.
  3. The personal loan accountant - who shall process personal loan requests, including approving/rejecting the requests, carrying out credit history checks and calculating the rate of interest.
  4. The home loan accountant - who shall process home loan requests, including approving/rejecting the requests, carrying out credit history checks and calculating the rate of interest.

To get started, download the version 2.0 of Akka for Java from http://akka.io/downloads and add the jars present in ‘akka-2.0-RC4\lib' to the classpath.

Next, create a new Java class "Bank.java" and add the following import statements :

import akka.actor.ActorRef;

import akka.actor.ActorSystem;

import akka.actor.Props;

import akka.actor.UntypedActor;

import akka.routing.RoundRobinRouter;

Now, create a few static nested classes under ‘Bank' that will act as messages (DTOs) and be passed to actors.

1. ‘LoanRequest' will contain the following elements and their corresponding getters/setters:

int requestedLoan;
int
accountBalance;

2. ‘PersonalLoanRequest' will extend ‘LoanRequest' and contain the following element and its corresponding getter:

final static String type="Personal";

3. ‘HomeLoanRequest' will extend ‘LoanRequest' and contain the following element and its corresponding getter:

final static String type="Home";

4. ‘LoanReply' will contain the following elements and their corresponding getters/setters:

String type;
boolean
approved;
int
rate;

Next, create a static nested class ‘PersonalLoanAccountant' under ‘Bank'.

public static class PersonalLoanAccountant extends UntypedActor {
public
int rateCaluclation(int requestedLoan, int accountBalance) {
if
(accountBalance/requestedLoan>=2)
return
5;
else

return
6;
}

public
void checkCreditHistory() {
for
(int i=0; i<1000; i++) {
continue
;
}
}
public
void onReceive(Object message) {
if
(message instanceof PersonalLoanRequest) {
PersonalLoanRequest request=PersonalLoanRequest.class.cast(message);
LoanReply reply = new LoanReply();
reply.setType(request.getType());
if
(request.getRequestedLoan()<request.getaccountBalance()) {
reply.setApproved(true);
reply.setRate(rateCaluclation(request.getRequestedLoan(), request.getaccountBalance()));
checkCreditHistory();
}
getSender().tell(reply);
} else {
unhandled(message);
}
}
}

The above class  serves as an actor in the system. It extends the ‘UntypedActor' base class provided by Akka and must define its ‘onReceive‘ method. This method acts as the mailbox and receives messages from other actors (or non-actors) in the system. If the message received is of type 'PersonalLoanRequest', then it can be processed by approving/rejecting the loan request, setting the rate of interest and checking the requestor's credit history. Once the processing is complete, the requestor uses the sender's reference (which is embedded in the message) to send the reply (LoanReply) to the requestor via the ‘getSender().tell()' method.

Now, create a similar static nested class ‘HomeLoanAccountant' under ‘Bank'

public static class HomeLoanAccountant extends UntypedActor {
public
int rateCaluclation(int requestedLoan, int accountBalance) {
if
(accountBalance/requestedLoan>=2)
return
7;
else

return
8;
}

public
void checkCreditHistory() {
for
(int i=0; i<2000; i++) {
continue
;
}
}
public
void onReceive(Object message) {
if
(message instanceof HomeLoanRequest) {
HomeLoanRequest request=HomeLoanRequest.class.cast(message);
LoanReply reply = new LoanReply();
reply.setType(request.getType());
if
(request.getRequestedLoan()<request.getaccountBalance()) {
reply.setApproved(true);
reply.setRate(rateCaluclation(request.getRequestedLoan(), request.getaccountBalance()));
checkCreditHistory();
}
getSender().tell(reply);
} else {
unhandled(message);
}
}
}

Now, create a static nested class ‘BackOffice' under ‘Bank':

public static class BackOffice extends UntypedActor {

ActorRef personalLoanAccountant=getContext().actorOf(new Props(PersonalLoanAccountant.class).withRouter(new RoundRobinRouter(2)));
ActorRef homeLoanAccountant=getContext().actorOf(new Props(HomeLoanAccountant.class).withRouter(new RoundRobinRouter(2)));

public void onReceive(Object message) {
if
(message instanceof PersonalLoanRequest) {
personalLoanAccountant.forward(message, getContext());
} else if (message instanceof HomeLoanRequest) {
homeLoanAccountant.forward(message, getContext());
} else {
unhandled(message);
}
}

}

The above class serves as an actor in the system and is purely used to route the incoming messages to PersonalLoanAccountant or HomeLoanAccountant, based on the type of message received. It defines actor references ‘personalLoanAccountant' and ‘homeLoanAccountant' to ‘PersonalLoanAccountant.class' and ‘HomeLoanAccountant.class', respectively. Each of these references initiates two instances of the actor it refers to and attaches a round-robin router to cycle through the actor instances. The ‘onReceive' method checks the type of the message received and forwards the message to either ‘PersonalLoanAccountant' or ‘HomeLoanAccountant' based on the message type. The ‘forward()' method helps ensure that the reference of the original sender is maintained in the message, so the receiver of the message (‘PersonalLoanAccountant' or ‘HomeLoanAccountant') can directly reply back to the message's original sender.

Now, create a static nested class ‘FrontDesk' under ‘Bank':

public static class FrontDesk extends UntypedActor {
int
approvedPersonalLoans=0;
int
approvedHomeLoans=0;
int
rejectedPersonalLoans=0;
int
rejectedHomeLoans=0;

ActorRef backOffice=getContext().actorOf(
new Props(BackOffice.class), "backOffice");

public
void maintainLoanApprovalStats(Object message) {
LoanReply reply = LoanReply.class.cast(message);
if
(reply.isApproved()) {
System.out.println(reply.getType()+" Loan Approved"+" at "+reply.getRate()+"% interest.");
if
(reply.getType().equals("Personal"))
++approvedPersonalLoans;
else
if(reply.getType().equals("Home"))
++approvedHomeLoans;
} else {
System.out.println(reply.getType()+" Loan Rejected");
if
(reply.getType().equals("Personal"))
++rejectedPersonalLoans;
else
if(reply.getType().equals("Home"))
++rejectedHomeLoans;
}
}

public void printLoanApprovalStats() {
System.out.println("--- REPORT ---");
System.out.println("Personal Loans Approved : "+approvedPersonalLoans);
System.out.println("Home Loans Approved : "+approvedHomeLoans);
System.out.println("Personal Loans Rejected : "+rejectedPersonalLoans);
System.out.println("Home Loans Rejected : "+rejectedHomeLoans);
}
public
void onReceive(Object message) {
if
(message instanceof LoanRequest) {
backOffice.tell(message, getSelf());
} else if (message instanceof LoanReply) {
maintainLoanApprovalStats(message);
} else if(message instanceof String && message.equals("printLoanApprovalStats")) {
printLoanApprovalStats();
getContext().stop(getSelf());
} else {
unhandled(message);
}
}
}

The above class serves as the final actor in the system. It creates a reference ‘backOffice' to the actor ‘BackOffice.class'. If the message received is of type ‘LoanRequest', it sends the message to ‘BackOffice' via the method ‘backOffice.tell()', which takes a message and the reference to the sender (acquired through the method ‘getSelf()') as arguments. If the message received is of type ‘LoanReply', it updates the counters to maintain the approved/rejected counts. If the message received is "printLoanApprovalStats", it prints the stats stored in the counters, and then proceeds to stop itself via the method ‘getContext().stop(getSelf())'. The actors follow a pattern of supervisor hierarchy, and thus this command trickles down the hierarchy chain and stops all four actors in the system.

Finally, write a few methods under ‘Bank' to submit requests to the ‘FrontOffice':

public static void main(String[] args) throws InterruptedException {
ActorSystem system = ActorSystem.create("bankSystem");
ActorRef frontDesk = system.actorOf(new Props(FrontDesk.class), "frontDesk");
submitLoanRequests
(frontDesk);
Thread.sleep(1000);
printLoanApprovalStats
(frontDesk);
system.shutdown();
}

public
static PersonalLoanRequest getPersonalLoanRequest() {
int
min=10000; int max=50000;
int
amount=min + (int)(Math.random() * ((max - min) + 1));
int
balance=min + (int)(Math.random() * ((max - min) + 1));
return
(new Bank()).new PersonalLoanRequest(amount, balance);
}

public
static HomeLoanRequest getHomeLoanRequest() {
int
min=50000; int max=90000;
int
amount=min + (int)(Math.random() * ((max - min) + 1));
int
balance=min + (int)(Math.random() * ((max - min) + 1));
return
(new Bank()).new HomeLoanRequest(amount, balance);
}

public static void submitLoanRequests(ActorRef frontDesk) {
for
(int i=0;i<1000;i++) {
frontDesk.tell(getPersonalLoanRequest());
frontDesk.tell(getHomeLoanRequest());
}
}

public static void printLoanApprovalStats(ActorRef frontDesk) {
frontDesk.tell("printLoanApprovalStats");
}

The method ‘main' creates an actor system ‘system' using the method ‘ActorSystem.create()'. It then creates a reference ‘frontDesk' to the actor ‘FrontDesk.class'. It uses this reference to send a 1000 requests each of types ‘PersonalLoanRequest' and ‘HomeLoanRequest' to ‘FrontDesk'. It then sleeps for a second, following which it sends the message "printLoanApprovalStats" to ‘FrontDesk'. Once done, it shuts down the actor system via the method ‘system.shutdown()'.

Conclusion
Running the above code will create a loan request processing system with concurrent processing capabilities, and all this without using a single synchronize/lock pattern. Moreover, the code doesn't need one to go into the low-level semantics of the JVM threading mechanism or use the complex ‘java.util.concurrent' package. This mechanism of concurrent processing using the Actor Model is truly more robust as multiple concurrent processes can communicate with each other without needing to use shared state variables.

More Stories By Sanat Vij

Sanat Vij is a professional software engineer currently working at CenturyLink. He has vast experience in developing high availability applications, configuring application servers, JVM profiling and memory management. He specializes in performance tuning of applications, reducing response times, and increasing stability.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


@ThingsExpo Stories
The Open Compute Project is a collective effort by Facebook and a number of players in the datacenter industry to bring lessons learned from the social media giant's giant IT deployment to the rest of the world. Datacenters account for 3% of global electricity consumption – about the same as all of Switzerland or the Czech Republic -- according to people I met at the recent Open Compute Summit in San Jose. With increasing mobility at the edge of the cloud and vast new dataflows being predicted with the growth of the Internet of Things (and The Coming Age of Many Zettabytes) in the near...
GENBAND has announced that SageNet is leveraging the Nuvia platform to deliver Unified Communications as a Service (UCaaS) to its large base of retail and enterprise customers. Nuvia’s cloud-based solution provides SageNet’s customers with a full suite of business communications and collaboration tools. Two large national SageNet retail customers have recently signed up to deploy the Nuvia platform and the company will continue to sell the service to new and existing customers. Nuvia’s capabilities include HD voice, video, multimedia messaging, mobility, conferencing, Web collaboration, deskt...
Wearable technology was dominant at this year’s International Consumer Electronics Show (CES) , and MWC was no exception to this trend. New versions of favorites, such as the Samsung Gear (three new products were released: the Gear 2, the Gear 2 Neo and the Gear Fit), shared the limelight with new wearables like Pebble Time Steel (the new premium version of the company’s previously released smartwatch) and the LG Watch Urbane. The most dramatic difference at MWC was an emphasis on presenting wearables as fashion accessories and moving away from the original clunky technology associated with t...
The WebRTC Summit 2014 New York, to be held June 9-11, 2015, at the Javits Center in New York, NY, announces that its Call for Papers is open. Topics include all aspects of improving IT delivery by eliminating waste through automated business models leveraging cloud technologies. WebRTC Summit is co-located with 16th International Cloud Expo, @ThingsExpo, Big Data Expo, and DevOps Summit.
SYS-CON Events announced today that Cisco, the worldwide leader in IT that transforms how people connect, communicate and collaborate, has been named “Gold Sponsor” of SYS-CON's 16th International Cloud Expo®, which will take place on June 9-11, 2015, at the Javits Center in New York City, NY. Cisco makes amazing things happen by connecting the unconnected. Cisco has shaped the future of the Internet by becoming the worldwide leader in transforming how people connect, communicate and collaborate. Cisco and our partners are building the platform for the Internet of Everything by connecting the...
15th Cloud Expo, which took place Nov. 4-6, 2014, at the Santa Clara Convention Center in Santa Clara, CA, expanded the conference content of @ThingsExpo, Big Data Expo, and DevOps Summit to include two developer events. IBM held a Bluemix Developer Playground on November 5 and ElasticBox held a Hackathon on November 6. Both events took place on the expo floor. The Bluemix Developer Playground, for developers of all levels, highlighted the ease of use of Bluemix, its services and functionality and provide short-term introductory projects that developers can complete between sessions.
SYS-CON Events announced today that robomq.io will exhibit at SYS-CON's @ThingsExpo, which will take place on June 9-11, 2015, at the Javits Center in New York City, NY. robomq.io is an interoperable and composable platform that connects any device to any application. It helps systems integrators and the solution providers build new and innovative products and service for industries requiring monitoring or intelligence from devices and sensors.
Temasys has announced senior management additions to its team. Joining are David Holloway as Vice President of Commercial and Nadine Yap as Vice President of Product. Over the past 12 months Temasys has doubled in size as it adds new customers and expands the development of its Skylink platform. Skylink leads the charge to move WebRTC, traditionally seen as a desktop, browser based technology, to become a ubiquitous web communications technology on web and mobile, as well as Internet of Things compatible devices.
The list of ‘new paradigm’ technologies that now surrounds us appears to be at an all time high. From cloud computing and Big Data analytics to Bring Your Own Device (BYOD) and the Internet of Things (IoT), today we have to deal with what the industry likes to call ‘paradigm shifts’ at every level of IT. This is disruption; of course, we understand that – change is almost always disruptive.
WebRTC is an up-and-coming standard that enables real-time voice and video to be directly embedded into browsers making the browser a primary user interface for communications and collaboration. WebRTC runs in a number of browsers today and is currently supported in over a billion installed browsers globally, across a range of platform OS and devices. Today, organizations that choose to deploy WebRTC applications and use a host machine that supports audio through USB or Bluetooth can use Plantronics products to connect and transit or receive the audio associated with the WebRTC session.
Docker is an excellent platform for organizations interested in running microservices. It offers portability and consistency between development and production environments, quick provisioning times, and a simple way to isolate services. In his session at DevOps Summit at 16th Cloud Expo, Shannon Williams, co-founder of Rancher Labs, will walk through these and other benefits of using Docker to run microservices, and provide an overview of RancherOS, a minimalist distribution of Linux designed expressly to run Docker. He will also discuss Rancher, an orchestration and service discovery platf...
SYS-CON Events announced today that Alert Logic, the leading provider of Security-as-a-Service solutions for the cloud, has been named “Bronze Sponsor” of SYS-CON's 16th International Cloud Expo® and DevOps Summit 2015 New York, which will take place June 9-11, 2015, at the Javits Center in New York City, NY, and the 17th International Cloud Expo® and DevOps Summit 2015 Silicon Valley, which will take place November 3–5, 2015, at the Santa Clara Convention Center in Santa Clara, CA.
Sonus Networks introduced the Sonus WebRTC Services Solution, a virtualized Web Real-Time Communications (WebRTC) offer, purpose-built for the Cloud. The WebRTC Services Solution provides signaling from WebRTC-to-WebRTC applications and interworking from WebRTC-to-Session Initiation Protocol (SIP), delivering advanced real-time communications capabilities on mobile applications and on websites, which are accessible via a browser.
SYS-CON Events announced today that Aria Systems, the leading innovator in recurring revenue, has been named “Bronze Sponsor” of SYS-CON's @ThingsExpo, which will take place on June 9–11, 2015, at the Javits Center in New York, NY. Proven by the world’s most demanding enterprises, including AAA NCNU, Constant Contact, Falck, Hootsuite, Pitney Bowes, Telekom Denmark, and VMware, Aria helps enterprises grow their recurring revenue businesses. With Aria’s end-to-end active monetization platform, global brands can get to market faster with a wider variety of products and services, while maximizin...
SYS-CON Media announced today that @WebRTCSummit Blog, the largest WebRTC resource in the world, has been launched. @WebRTCSummit Blog offers top articles, news stories, and blog posts from the world's well-known experts and guarantees better exposure for its authors than any other publication. @WebRTCSummit Blog can be bookmarked ▸ Here @WebRTCSummit conference site can be bookmarked ▸ Here
SYS-CON Events announced today that Vitria Technology, Inc. will exhibit at SYS-CON’s @ThingsExpo, which will take place on June 9-11, 2015, at the Javits Center in New York City, NY. Vitria will showcase the company’s new IoT Analytics Platform through live demonstrations at booth #330. Vitria’s IoT Analytics Platform, fully integrated and powered by an operational intelligence engine, enables customers to rapidly build and operationalize advanced analytics to deliver timely business outcomes for use cases across the industrial, enterprise, and consumer segments.
SYS-CON Events announced today that Solgenia will exhibit at SYS-CON's 16th International Cloud Expo®, which will take place on June 9-11, 2015, at the Javits Center in New York City, NY, and the 17th International Cloud Expo®, which will take place on November 3–5, 2015, at the Santa Clara Convention Center in Santa Clara, CA. Solgenia is the global market leader in Cloud Collaboration and Cloud Infrastructure software solutions. Designed to “Bridge the Gap” between Personal and Professional Social, Mobile and Cloud user experiences, our solutions help large and medium-sized organizations dr...
SYS-CON Events announced today that Liaison Technologies, a leading provider of data management and integration cloud services and solutions, has been named "Silver Sponsor" of SYS-CON's 16th International Cloud Expo®, which will take place on June 9-11, 2015, at the Javits Center in New York, NY. Liaison Technologies is a recognized market leader in providing cloud-enabled data integration and data management solutions to break down complex information barriers, enabling enterprises to make smarter decisions, faster.
Connected devices and the Internet of Things are getting significant momentum in 2014. In his session at Internet of @ThingsExpo, Jim Hunter, Chief Scientist & Technology Evangelist at Greenwave Systems, examined three key elements that together will drive mass adoption of the IoT before the end of 2015. The first element is the recent advent of robust open source protocols (like AllJoyn and WebRTC) that facilitate M2M communication. The second is broad availability of flexible, cost-effective storage designed to handle the massive surge in back-end data in a world where timely analytics is e...
SYS-CON Events announced today that Akana, formerly SOA Software, has been named “Bronze Sponsor” of SYS-CON's 16th International Cloud Expo® New York, which will take place June 9-11, 2015, at the Javits Center in New York City, NY. Akana’s comprehensive suite of API Management, API Security, Integrated SOA Governance, and Cloud Integration solutions helps businesses accelerate digital transformation by securely extending their reach across multiple channels – mobile, cloud and Internet of Things. Akana enables enterprises to share data as APIs, connect and integrate applications, drive part...