Skip to content

Commit fe522fd

Browse files
feat: Implement Actor Model pattern
* feat: Implement Actor Model pattern #3232 * feat: Implement Actor Model pattern #3232 * feat: update Actor Model implementation with multi-actor logic #3251 * feat: update Actor Model implementation with multi-actor logic and loose coupling #3251 * test: add unit test for actor model #3251 * test: add test for App.java to increase coverage * docs: add complete README for Actor Model pattern also implemented changes #3251
1 parent 1cde704 commit fe522fd

File tree

12 files changed

+728
-0
lines changed

12 files changed

+728
-0
lines changed

actor-model/README.md

+201
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
---
2+
title: "Actor Model Pattern in Java: Building Concurrent Systems with Elegance"
3+
shortTitle: Actor Model
4+
description: "Explore the Actor Model pattern in Java with real-world examples and practical implementation. Learn how to build scalable, message-driven systems using actors, messages, and asynchronous communication."
5+
category: Concurrency
6+
language: en
7+
tag:
8+
- Concurrency
9+
- Messaging
10+
- Isolation
11+
- Asynchronous
12+
- Distributed Systems
13+
- Actor Model
14+
---
15+
16+
## Also Known As
17+
18+
- Message-passing concurrency
19+
- Actor-based concurrency
20+
21+
---
22+
23+
## Intent of Actor Model Pattern
24+
25+
The Actor Model pattern enables the construction of highly concurrent, distributed, and fault-tolerant systems by using isolated components (actors) that interact exclusively through asynchronous message passing.
26+
27+
---
28+
29+
## Detailed Explanation of Actor Model Pattern with Real-World Examples
30+
31+
### 📦 Real-world Example
32+
33+
Imagine a customer service system:
34+
- Each **customer support agent** is an **actor**.
35+
- Customers **send questions (messages)** to agents.
36+
- Each agent handles one request at a time and can **respond asynchronously** without interfering with other agents.
37+
38+
---
39+
40+
### 🧠 In Plain Words
41+
42+
> "Actors are like independent workers that never share memory and only communicate through messages."
43+
44+
---
45+
46+
### 📖 Wikipedia Says
47+
48+
> [Actor model](https://en.wikipedia.org/wiki/Actor_model) is a mathematical model of concurrent computation that treats "actors" as the universal primitives of concurrent computation.
49+
50+
---
51+
52+
### 🧹 Architecture Diagram
53+
54+
![UML Class Diagram](./etc/Actor_Model_UML_Class_Diagram.png)
55+
56+
---
57+
58+
## Programmatic Example of Actor Model Pattern in Java
59+
60+
### Actor.java
61+
62+
```java
63+
public abstract class Actor implements Runnable {
64+
65+
@Setter @Getter private String actorId;
66+
private final BlockingQueue<Message> mailbox = new LinkedBlockingQueue<>();
67+
private volatile boolean active = true;
68+
69+
70+
public void send(Message message) {
71+
mailbox.add(message);
72+
}
73+
74+
public void stop() {
75+
active = false;
76+
}
77+
78+
@Override
79+
public void run() {
80+
81+
}
82+
83+
protected abstract void onReceive(Message message);
84+
}
85+
86+
```
87+
88+
### Message.java
89+
90+
```java
91+
92+
@AllArgsConstructor
93+
@Getter
94+
@Setter
95+
public class Message {
96+
private final String content;
97+
private final String senderId;
98+
}
99+
```
100+
101+
### ActorSystem.java
102+
103+
```java
104+
public class ActorSystem {
105+
public void startActor(Actor actor) {
106+
String actorId = "actor-" + idCounter.incrementAndGet(); // Generate a new and unique ID
107+
actor.setActorId(actorId); // assign the actor it's ID
108+
actorRegister.put(actorId, actor); // Register and save the actor with it's ID
109+
executor.submit(actor); // Run the actor in a thread
110+
}
111+
public Actor getActorById(String actorId) {
112+
return actorRegister.get(actorId); // Find by Id
113+
}
114+
115+
public void shutdown() {
116+
executor.shutdownNow(); // Stop all threads
117+
}
118+
}
119+
```
120+
121+
### App.java
122+
123+
```java
124+
public class App {
125+
public static void main(String[] args) {
126+
ActorSystem system = new ActorSystem();
127+
Actor srijan = new ExampleActor(system);
128+
Actor ansh = new ExampleActor2(system);
129+
130+
system.startActor(srijan);
131+
system.startActor(ansh);
132+
ansh.send(new Message("Hello ansh", srijan.getActorId()));
133+
srijan.send(new Message("Hello srijan!", ansh.getActorId()));
134+
135+
Thread.sleep(1000); // Give time for messages to process
136+
137+
srijan.stop(); // Stop the actor gracefully
138+
ansh.stop();
139+
system.shutdown(); // Stop the actor system
140+
}
141+
}
142+
```
143+
144+
---
145+
146+
## When to Use the Actor Model Pattern in Java
147+
148+
- When building **concurrent or distributed systems**
149+
- When you want **no shared mutable state**
150+
- When you need **asynchronous, message-driven communication**
151+
- When components should be **isolated and loosely coupled**
152+
153+
---
154+
155+
## Actor Model Pattern Java Tutorials
156+
157+
- [Baeldung – Akka with Java](https://www.baeldung.com/java-akka)
158+
- [Vaughn Vernon – Reactive Messaging Patterns](https://vaughnvernon.co/?p=1143)
159+
160+
---
161+
162+
## Real-World Applications of Actor Model Pattern in Java
163+
164+
- [Akka Framework](https://akka.io/)
165+
- [Erlang and Elixir concurrency](https://www.erlang.org/)
166+
- [Microsoft Orleans](https://learn.microsoft.com/en-us/dotnet/orleans/)
167+
- JVM-based game engines and simulators
168+
169+
---
170+
171+
## Benefits and Trade-offs of Actor Model Pattern
172+
173+
### ✅ Benefits
174+
- High concurrency support
175+
- Easy scaling across threads or machines
176+
- Fault isolation and recovery
177+
- Message ordering within actors
178+
179+
### ⚠️ Trade-offs
180+
- Harder to debug due to asynchronous behavior
181+
- Slight performance overhead due to message queues
182+
- More complex to design than simple method calls
183+
184+
---
185+
186+
## Related Java Design Patterns
187+
188+
- [Command Pattern](../command)
189+
- [Mediator Pattern](../mediator)
190+
- [Event-Driven Architecture](../event-driven-architecture)
191+
- [Observer Pattern](../observer)
192+
193+
---
194+
195+
## References and Credits
196+
197+
- *Programming Erlang*, Joe Armstrong
198+
- *Reactive Design Patterns*, Roland Kuhn
199+
- *The Actor Model in 10 Minutes*, [InfoQ Article](https://www.infoq.com/articles/actor-model/)
200+
- [Akka Documentation](https://doc.akka.io/docs/akka/current/index.html)
201+
Loading

actor-model/etc/actor-model.urm.puml

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
@startuml actor-model
2+
3+
title Actor Model - UML Class Diagram
4+
5+
class ActorSystem {
6+
+actorOf(actor: Actor): Actor
7+
+shutdown(): void
8+
}
9+
10+
class Actor {
11+
-mailbox: BlockingQueue<Message>
12+
-active: boolean
13+
+send(message: Message): void
14+
+stop(): void
15+
+run(): void
16+
#onReceive(message: Message): void
17+
}
18+
19+
class ExampleActor {
20+
+onReceive(message: Message): void
21+
}
22+
23+
class Message {
24+
-content: String
25+
-sender: Actor
26+
+getContent(): String
27+
+getSender(): Actor
28+
}
29+
30+
ActorSystem --> Actor : creates
31+
Actor <|-- ExampleActor : extends
32+
Actor --> Message : processes
33+
ExampleActor --> Message : uses
34+
35+
@enduml

actor-model/pom.xml

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
5+
6+
The MIT License
7+
Copyright © 2014-2022 Ilkka Seppälä
8+
9+
Permission is hereby granted, free of charge, to any person obtaining a copy
10+
of this software and associated documentation files (the "Software"), to deal
11+
in the Software without restriction, including without limitation the rights
12+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
copies of the Software, and to permit persons to whom the Software is
14+
furnished to do so, subject to the following conditions:
15+
16+
The above copyright notice and this permission notice shall be included in
17+
all copies or substantial portions of the Software.
18+
19+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
THE SOFTWARE.
26+
27+
-->
28+
<project xmlns="http://maven.apache.org/POM/4.0.0"
29+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
30+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
31+
http://maven.apache.org/xsd/maven-4.0.0.xsd">
32+
33+
<modelVersion>4.0.0</modelVersion>
34+
35+
<parent>
36+
<groupId>com.iluwatar</groupId>
37+
<artifactId>java-design-patterns</artifactId>
38+
<version>1.26.0-SNAPSHOT</version>
39+
</parent>
40+
41+
<artifactId>actor-model</artifactId>
42+
<name>Actor Model</name>
43+
44+
<!-- Force unified JUnit version to avoid classpath mismatches -->
45+
<dependencyManagement>
46+
<dependencies>
47+
<dependency>
48+
<groupId>org.junit</groupId>
49+
<artifactId>junit-bom</artifactId>
50+
<version>5.11.0</version>
51+
<type>pom</type>
52+
<scope>import</scope>
53+
</dependency>
54+
</dependencies>
55+
</dependencyManagement>
56+
57+
<dependencies>
58+
<dependency>
59+
<groupId>org.junit.jupiter</groupId>
60+
<artifactId>junit-jupiter-api</artifactId>
61+
<scope>test</scope>
62+
</dependency>
63+
<dependency>
64+
<groupId>org.junit.jupiter</groupId>
65+
<artifactId>junit-jupiter-engine</artifactId>
66+
<scope>test</scope>
67+
</dependency>
68+
<dependency>
69+
<groupId>org.junit.platform</groupId>
70+
<artifactId>junit-platform-launcher</artifactId>
71+
<scope>test</scope>
72+
</dependency>
73+
<dependency>
74+
<groupId>org.slf4j</groupId>
75+
<artifactId>slf4j-api</artifactId>
76+
</dependency>
77+
<dependency>
78+
<groupId>ch.qos.logback</groupId>
79+
<artifactId>logback-classic</artifactId>
80+
</dependency>
81+
</dependencies>
82+
83+
<build>
84+
<plugins>
85+
<!-- Assembly plugin for creating fat JARs -->
86+
<plugin>
87+
<groupId>org.apache.maven.plugins</groupId>
88+
<artifactId>maven-assembly-plugin</artifactId>
89+
<version>3.3.0</version>
90+
<configuration>
91+
<descriptorRefs>
92+
<descriptorRef>jar-with-dependencies</descriptorRef>
93+
</descriptorRefs>
94+
<archive>
95+
<manifest>
96+
<mainClass>com.iluwatar.actormodel.App</mainClass>
97+
</manifest>
98+
</archive>
99+
</configuration>
100+
<executions>
101+
<execution>
102+
<id>make-assembly</id>
103+
<phase>package</phase>
104+
<goals>
105+
<goal>single</goal>
106+
</goals>
107+
</execution>
108+
</executions>
109+
110+
</plugin>
111+
</plugins>
112+
</build>
113+
114+
</project>

0 commit comments

Comments
 (0)