mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-05-14 06:58:54 +00:00
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
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
---
|
||||
title: "Actor Model Pattern in Java: Building Concurrent Systems with Elegance"
|
||||
shortTitle: Actor Model
|
||||
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."
|
||||
category: Concurrency
|
||||
language: en
|
||||
tag:
|
||||
- Concurrency
|
||||
- Messaging
|
||||
- Isolation
|
||||
- Asynchronous
|
||||
- Distributed Systems
|
||||
- Actor Model
|
||||
---
|
||||
|
||||
## Also Known As
|
||||
|
||||
- Message-passing concurrency
|
||||
- Actor-based concurrency
|
||||
|
||||
---
|
||||
|
||||
## Intent of Actor Model Pattern
|
||||
|
||||
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.
|
||||
|
||||
---
|
||||
|
||||
## Detailed Explanation of Actor Model Pattern with Real-World Examples
|
||||
|
||||
### 📦 Real-world Example
|
||||
|
||||
Imagine a customer service system:
|
||||
- Each **customer support agent** is an **actor**.
|
||||
- Customers **send questions (messages)** to agents.
|
||||
- Each agent handles one request at a time and can **respond asynchronously** without interfering with other agents.
|
||||
|
||||
---
|
||||
|
||||
### 🧠 In Plain Words
|
||||
|
||||
> "Actors are like independent workers that never share memory and only communicate through messages."
|
||||
|
||||
---
|
||||
|
||||
### 📖 Wikipedia Says
|
||||
|
||||
> [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.
|
||||
|
||||
---
|
||||
|
||||
### 🧹 Architecture Diagram
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Programmatic Example of Actor Model Pattern in Java
|
||||
|
||||
### Actor.java
|
||||
|
||||
```java
|
||||
public abstract class Actor implements Runnable {
|
||||
|
||||
@Setter @Getter private String actorId;
|
||||
private final BlockingQueue<Message> mailbox = new LinkedBlockingQueue<>();
|
||||
private volatile boolean active = true;
|
||||
|
||||
|
||||
public void send(Message message) {
|
||||
mailbox.add(message);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
active = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
}
|
||||
|
||||
protected abstract void onReceive(Message message);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Message.java
|
||||
|
||||
```java
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
public class Message {
|
||||
private final String content;
|
||||
private final String senderId;
|
||||
}
|
||||
```
|
||||
|
||||
### ActorSystem.java
|
||||
|
||||
```java
|
||||
public class ActorSystem {
|
||||
public void startActor(Actor actor) {
|
||||
String actorId = "actor-" + idCounter.incrementAndGet(); // Generate a new and unique ID
|
||||
actor.setActorId(actorId); // assign the actor it's ID
|
||||
actorRegister.put(actorId, actor); // Register and save the actor with it's ID
|
||||
executor.submit(actor); // Run the actor in a thread
|
||||
}
|
||||
public Actor getActorById(String actorId) {
|
||||
return actorRegister.get(actorId); // Find by Id
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
executor.shutdownNow(); // Stop all threads
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### App.java
|
||||
|
||||
```java
|
||||
public class App {
|
||||
public static void main(String[] args) {
|
||||
ActorSystem system = new ActorSystem();
|
||||
Actor srijan = new ExampleActor(system);
|
||||
Actor ansh = new ExampleActor2(system);
|
||||
|
||||
system.startActor(srijan);
|
||||
system.startActor(ansh);
|
||||
ansh.send(new Message("Hello ansh", srijan.getActorId()));
|
||||
srijan.send(new Message("Hello srijan!", ansh.getActorId()));
|
||||
|
||||
Thread.sleep(1000); // Give time for messages to process
|
||||
|
||||
srijan.stop(); // Stop the actor gracefully
|
||||
ansh.stop();
|
||||
system.shutdown(); // Stop the actor system
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## When to Use the Actor Model Pattern in Java
|
||||
|
||||
- When building **concurrent or distributed systems**
|
||||
- When you want **no shared mutable state**
|
||||
- When you need **asynchronous, message-driven communication**
|
||||
- When components should be **isolated and loosely coupled**
|
||||
|
||||
---
|
||||
|
||||
## Actor Model Pattern Java Tutorials
|
||||
|
||||
- [Baeldung – Akka with Java](https://www.baeldung.com/java-akka)
|
||||
- [Vaughn Vernon – Reactive Messaging Patterns](https://vaughnvernon.co/?p=1143)
|
||||
|
||||
---
|
||||
|
||||
## Real-World Applications of Actor Model Pattern in Java
|
||||
|
||||
- [Akka Framework](https://akka.io/)
|
||||
- [Erlang and Elixir concurrency](https://www.erlang.org/)
|
||||
- [Microsoft Orleans](https://learn.microsoft.com/en-us/dotnet/orleans/)
|
||||
- JVM-based game engines and simulators
|
||||
|
||||
---
|
||||
|
||||
## Benefits and Trade-offs of Actor Model Pattern
|
||||
|
||||
### ✅ Benefits
|
||||
- High concurrency support
|
||||
- Easy scaling across threads or machines
|
||||
- Fault isolation and recovery
|
||||
- Message ordering within actors
|
||||
|
||||
### ⚠️ Trade-offs
|
||||
- Harder to debug due to asynchronous behavior
|
||||
- Slight performance overhead due to message queues
|
||||
- More complex to design than simple method calls
|
||||
|
||||
---
|
||||
|
||||
## Related Java Design Patterns
|
||||
|
||||
- [Command Pattern](../command)
|
||||
- [Mediator Pattern](../mediator)
|
||||
- [Event-Driven Architecture](../event-driven-architecture)
|
||||
- [Observer Pattern](../observer)
|
||||
|
||||
---
|
||||
|
||||
## References and Credits
|
||||
|
||||
- *Programming Erlang*, Joe Armstrong
|
||||
- *Reactive Design Patterns*, Roland Kuhn
|
||||
- *The Actor Model in 10 Minutes*, [InfoQ Article](https://www.infoq.com/articles/actor-model/)
|
||||
- [Akka Documentation](https://doc.akka.io/docs/akka/current/index.html)
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
@@ -0,0 +1,35 @@
|
||||
@startuml actor-model
|
||||
|
||||
title Actor Model - UML Class Diagram
|
||||
|
||||
class ActorSystem {
|
||||
+actorOf(actor: Actor): Actor
|
||||
+shutdown(): void
|
||||
}
|
||||
|
||||
class Actor {
|
||||
-mailbox: BlockingQueue<Message>
|
||||
-active: boolean
|
||||
+send(message: Message): void
|
||||
+stop(): void
|
||||
+run(): void
|
||||
#onReceive(message: Message): void
|
||||
}
|
||||
|
||||
class ExampleActor {
|
||||
+onReceive(message: Message): void
|
||||
}
|
||||
|
||||
class Message {
|
||||
-content: String
|
||||
-sender: Actor
|
||||
+getContent(): String
|
||||
+getSender(): Actor
|
||||
}
|
||||
|
||||
ActorSystem --> Actor : creates
|
||||
Actor <|-- ExampleActor : extends
|
||||
Actor --> Message : processes
|
||||
ExampleActor --> Message : uses
|
||||
|
||||
@enduml
|
||||
@@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
|
||||
The MIT License
|
||||
Copyright © 2014-2022 Ilkka Seppälä
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.26.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>actor-model</artifactId>
|
||||
<name>Actor Model</name>
|
||||
|
||||
<!-- Force unified JUnit version to avoid classpath mismatches -->
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit</groupId>
|
||||
<artifactId>junit-bom</artifactId>
|
||||
<version>5.11.0</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.platform</groupId>
|
||||
<artifactId>junit-platform-launcher</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- Assembly plugin for creating fat JARs -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<configuration>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>com.iluwatar.actormodel.App</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.actormodel;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
public abstract class Actor implements Runnable {
|
||||
|
||||
@Setter @Getter private String actorId;
|
||||
private final BlockingQueue<Message> mailbox = new LinkedBlockingQueue<>();
|
||||
private volatile boolean active =
|
||||
true; // always read from main memory and written back to main memory,
|
||||
|
||||
// rather than being cached in a thread's local memory. To make it consistent to all Actors
|
||||
|
||||
public void send(Message message) {
|
||||
mailbox.add(message); // Add message to queue
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
active = false; // Stop the actor loop
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (active) {
|
||||
try {
|
||||
Message message = mailbox.take(); // Wait for a message
|
||||
onReceive(message); // Process it
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Child classes must define what to do with a message
|
||||
protected abstract void onReceive(Message message);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.actormodel;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class ActorSystem {
|
||||
private final ExecutorService executor = Executors.newCachedThreadPool();
|
||||
private final ConcurrentHashMap<String, Actor> actorRegister = new ConcurrentHashMap<>();
|
||||
private final AtomicInteger idCounter = new AtomicInteger(0);
|
||||
|
||||
public void startActor(Actor actor) {
|
||||
String actorId = "actor-" + idCounter.incrementAndGet(); // Generate a new and unique ID
|
||||
actor.setActorId(actorId); // assign the actor it's ID
|
||||
actorRegister.put(actorId, actor); // Register and save the actor with it's ID
|
||||
executor.submit(actor); // Run the actor in a thread
|
||||
}
|
||||
|
||||
public Actor getActorById(String actorId) {
|
||||
return actorRegister.get(actorId); // Find by Id
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
executor.shutdownNow(); // Stop all threads
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The Actor Model is a design pattern used to handle concurrency in a safe, scalable, and
|
||||
* message-driven way.
|
||||
*
|
||||
* <p>In the Actor Model: - An **Actor** is an independent unit that has its own state and behavior.
|
||||
* - Actors **communicate only through messages** — they do not share memory. - An **ActorSystem**
|
||||
* is responsible for creating, starting, and managing the lifecycle of actors. - Messages are
|
||||
* delivered asynchronously, and each actor processes them one at a time.
|
||||
*
|
||||
* <p>💡 Key benefits: - No shared memory = no need for complex thread-safety - Easy to scale with
|
||||
* many actors - Suitable for highly concurrent or distributed systems
|
||||
*
|
||||
* <p>🔍 This example demonstrates the Actor Model: - `ActorSystem` starts two actors: `srijan` and
|
||||
* `ansh`. - `ExampleActor` and `ExampleActor2` extend the `Actor` class and override the
|
||||
* `onReceive()` method to handle messages. - Actors communicate using `send()` to pass `Message`
|
||||
* objects that include the message content and sender's ID. - The actors process messages
|
||||
* **asynchronously in separate threads**, and we allow a short delay (`Thread.sleep`) to let them
|
||||
* run. - The system is shut down gracefully at the end.
|
||||
*/
|
||||
package com.iluwatar.actormodel;
|
||||
|
||||
public class App {
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
ActorSystem system = new ActorSystem();
|
||||
Actor srijan = new ExampleActor(system);
|
||||
Actor ansh = new ExampleActor2(system);
|
||||
|
||||
system.startActor(srijan);
|
||||
system.startActor(ansh);
|
||||
ansh.send(new Message("Hello ansh", srijan.getActorId()));
|
||||
srijan.send(new Message("Hello srijan!", ansh.getActorId()));
|
||||
|
||||
Thread.sleep(1000); // Give time for messages to process
|
||||
|
||||
srijan.stop(); // Stop the actor gracefully
|
||||
ansh.stop();
|
||||
system.shutdown(); // Stop the actor system
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.actormodel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class ExampleActor extends Actor {
|
||||
private final ActorSystem actorSystem;
|
||||
@Getter private final List<String> receivedMessages = new ArrayList<>();
|
||||
|
||||
public ExampleActor(ActorSystem actorSystem) {
|
||||
this.actorSystem = actorSystem;
|
||||
}
|
||||
|
||||
// Logger log = Logger.getLogger(getClass().getName());
|
||||
|
||||
@Override
|
||||
protected void onReceive(Message message) {
|
||||
LOGGER.info(
|
||||
"[{}]Received : {} from : [{}]", getActorId(), message.getContent(), message.getSenderId());
|
||||
Actor sender = actorSystem.getActorById(message.getSenderId()); // sender actor id
|
||||
// Reply of the message
|
||||
if (sender != null && !message.getSenderId().equals(getActorId())) {
|
||||
sender.send(new Message("I got your message ", getActorId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.actormodel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class ExampleActor2 extends Actor {
|
||||
private final ActorSystem actorSystem;
|
||||
@Getter private final List<String> receivedMessages = new ArrayList<>();
|
||||
|
||||
public ExampleActor2(ActorSystem actorSystem) {
|
||||
this.actorSystem = actorSystem;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onReceive(Message message) {
|
||||
receivedMessages.add(message.getContent());
|
||||
LOGGER.info("[{}]Received : {}", getActorId(), message.getContent());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.actormodel;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public class Message {
|
||||
private final String content;
|
||||
private final String senderId;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.actor;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import com.iluwatar.actormodel.ActorSystem;
|
||||
import com.iluwatar.actormodel.App;
|
||||
import com.iluwatar.actormodel.ExampleActor;
|
||||
import com.iluwatar.actormodel.ExampleActor2;
|
||||
import com.iluwatar.actormodel.Message;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class ActorModelTest {
|
||||
@Test
|
||||
void testMainMethod() throws InterruptedException {
|
||||
App.main(new String[] {});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessagePassing() throws InterruptedException {
|
||||
ActorSystem system = new ActorSystem();
|
||||
|
||||
ExampleActor srijan = new ExampleActor(system);
|
||||
ExampleActor2 ansh = new ExampleActor2(system);
|
||||
|
||||
system.startActor(srijan);
|
||||
system.startActor(ansh);
|
||||
|
||||
// Ansh recieves a message from Srijan
|
||||
ansh.send(new Message("Hello ansh", srijan.getActorId()));
|
||||
|
||||
// Wait briefly to allow async processing
|
||||
Thread.sleep(200);
|
||||
|
||||
// Check that Srijan received the message
|
||||
assertTrue(
|
||||
ansh.getReceivedMessages().contains("Hello ansh"),
|
||||
"ansh should receive the message from Srijan");
|
||||
}
|
||||
}
|
||||
@@ -71,6 +71,7 @@
|
||||
<sonar.projectName>Java Design Patterns</sonar.projectName>
|
||||
</properties>
|
||||
<modules>
|
||||
|
||||
<module>abstract-document</module>
|
||||
<module>abstract-factory</module>
|
||||
<module>active-object</module>
|
||||
@@ -243,6 +244,8 @@
|
||||
<module>virtual-proxy</module>
|
||||
<module>visitor</module>
|
||||
<module>backpressure</module>
|
||||
<module>actor-model</module>
|
||||
|
||||
</modules>
|
||||
<repositories>
|
||||
<repository>
|
||||
|
||||
Reference in New Issue
Block a user