From 9dbffa269ac8d19997eacfd6ac4f79d68c11df9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Tue, 7 May 2024 15:54:49 +0300 Subject: [PATCH] docs: update master-worker --- master-worker-pattern/README.md | 106 ------------- master-worker/README.md | 149 ++++++++++++++++++ .../etc/master-worker-pattern.urm.png | Bin .../etc/master-worker-pattern.urm.puml | 0 .../pom.xml | 2 +- .../java/com/iluwatar/masterworker/App.java | 0 .../com/iluwatar/masterworker/ArrayInput.java | 0 .../iluwatar/masterworker/ArrayResult.java | 0 .../masterworker/ArrayUtilityMethods.java | 0 .../java/com/iluwatar/masterworker/Input.java | 0 .../com/iluwatar/masterworker/Result.java | 0 .../system/ArrayTransposeMasterWorker.java | 0 .../masterworker/system/MasterWorker.java | 0 .../systemmaster/ArrayTransposeMaster.java | 0 .../system/systemmaster/Master.java | 8 +- .../systemworkers/ArrayTransposeWorker.java | 0 .../system/systemworkers/Worker.java | 8 +- .../iluwatar/masterworker/ArrayInputTest.java | 0 .../masterworker/ArrayUtilityMethodsTest.java | 0 .../ArrayTransposeMasterWorkerTest.java | 0 .../ArrayTransposeWorkerTest.java | 0 pom.xml | 2 +- 22 files changed, 157 insertions(+), 118 deletions(-) delete mode 100644 master-worker-pattern/README.md create mode 100644 master-worker/README.md rename {master-worker-pattern => master-worker}/etc/master-worker-pattern.urm.png (100%) rename {master-worker-pattern => master-worker}/etc/master-worker-pattern.urm.puml (100%) rename {master-worker-pattern => master-worker}/pom.xml (98%) rename {master-worker-pattern => master-worker}/src/main/java/com/iluwatar/masterworker/App.java (100%) rename {master-worker-pattern => master-worker}/src/main/java/com/iluwatar/masterworker/ArrayInput.java (100%) rename {master-worker-pattern => master-worker}/src/main/java/com/iluwatar/masterworker/ArrayResult.java (100%) rename {master-worker-pattern => master-worker}/src/main/java/com/iluwatar/masterworker/ArrayUtilityMethods.java (100%) rename {master-worker-pattern => master-worker}/src/main/java/com/iluwatar/masterworker/Input.java (100%) rename {master-worker-pattern => master-worker}/src/main/java/com/iluwatar/masterworker/Result.java (100%) rename {master-worker-pattern => master-worker}/src/main/java/com/iluwatar/masterworker/system/ArrayTransposeMasterWorker.java (100%) rename {master-worker-pattern => master-worker}/src/main/java/com/iluwatar/masterworker/system/MasterWorker.java (100%) rename {master-worker-pattern => master-worker}/src/main/java/com/iluwatar/masterworker/system/systemmaster/ArrayTransposeMaster.java (100%) rename {master-worker-pattern => master-worker}/src/main/java/com/iluwatar/masterworker/system/systemmaster/Master.java (97%) rename {master-worker-pattern => master-worker}/src/main/java/com/iluwatar/masterworker/system/systemworkers/ArrayTransposeWorker.java (100%) rename {master-worker-pattern => master-worker}/src/main/java/com/iluwatar/masterworker/system/systemworkers/Worker.java (95%) rename {master-worker-pattern => master-worker}/src/test/java/com/iluwatar/masterworker/ArrayInputTest.java (100%) rename {master-worker-pattern => master-worker}/src/test/java/com/iluwatar/masterworker/ArrayUtilityMethodsTest.java (100%) rename {master-worker-pattern => master-worker}/src/test/java/com/iluwatar/masterworker/system/ArrayTransposeMasterWorkerTest.java (100%) rename {master-worker-pattern => master-worker}/src/test/java/com/iluwatar/masterworker/system/systemworkers/ArrayTransposeWorkerTest.java (100%) diff --git a/master-worker-pattern/README.md b/master-worker-pattern/README.md deleted file mode 100644 index 32f239078..000000000 --- a/master-worker-pattern/README.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -title: Master-Worker -category: Concurrency -language: en -tag: - - Performance ---- - -## Also known as - -> Master-slave or Map-reduce - -## Intent - -> Used for centralised parallel processing. - -## Class diagram -![alt text](./etc/master-worker-pattern.urm.png "Master-Worker pattern class diagram") - -## Explanation - -Real World Example ->Imagine you have a large stack of papers to grade as a teacher. You decide to hire several teaching assistants to help you. You, as the "master," distribute different papers to each teaching assistant, they grade them independently, and return the graded papers to you. Finally, you collect all the graded papers, review them, and calculate the final grades. This process of dividing work among assistants, parallel processing, and aggregating results is similar to the Master-Worker pattern. - -In Plain Words ->The Master-Worker pattern is like a boss (the master) assigning tasks to workers and then combining the results. It's a way to efficiently break down a big job into smaller pieces that can be done concurrently. - -Wikipedia Says ->According to [Wikipedia](https://en.wikipedia.org/wiki/Master/slave_(technology)), the Master-Worker pattern, also known as Master-Slave or Map-Reduce, is a design pattern used in software engineering for parallel processing. In this pattern, a "master" component divides a complex task into smaller subtasks and assigns them to multiple "worker" components. Each worker processes its assigned subtask independently, and the master collects and combines the results to produce the final output. - -Programmatic Example - -```java -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.*; - -// Define a task that workers (teaching assistants) will perform -class GradingWorkerTask implements Callable { - private int paperNumber; - - public GradingWorkerTask(int paperNumber) { - this.paperNumber = paperNumber; - } - - @Override - public Integer call() throws Exception { - // Simulate grading a paper (e.g., assigning a score) - int score = (int) (Math.random() * 100); // Assign a random score - // Simulate some grading time - Thread.sleep((int) (Math.random() * 1000)); - System.out.println("Graded paper #" + paperNumber + " with a score of " + score); - return score; - } -} -``` - -```java -public class PaperGrading { - public static void main(String[] args) { - int totalPapersToGrade = 20; // Total number of papers to grade - int numberOfTeachingAssistants = 3; // Number of teaching assistants - - // Create a thread pool with a fixed number of teaching assistants (workers) - ExecutorService executor = Executors.newFixedThreadPool(numberOfTeachingAssistants); - - // Create and submit grading tasks to the executor for each paper - List> results = new ArrayList<>(); - for (int paperNumber = 1; paperNumber <= totalPapersToGrade; paperNumber++) { - results.add(executor.submit(new GradingWorkerTask(paperNumber))); - } - - // Shutdown the executor to prevent new tasks from being submitted - executor.shutdown(); - - // Collect and analyze the grading results - int totalScore = 0; - for (Future result : results) { - try { - // Get the score of each graded paper and calculate the total score - totalScore += result.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - } - - double averageScore = (double) totalScore / totalPapersToGrade; - - System.out.println("Grading completed."); - System.out.println("Total papers graded: " + totalPapersToGrade); - System.out.println("Total score: " + totalScore); - System.out.println("Average score: " + averageScore); - } -} -``` - -## Applicability -This pattern can be used when data can be divided into multiple parts, all of which need to go through the same computation to give a result, which need to be aggregated to get the final result. - -## Explanation -In this pattern, parallel processing is performed using a system consisting of a master and some number of workers, where a master divides the work among the workers, gets the result back from them and assimilates all the results to give final result. The only communication is between the master and the worker - none of the workers communicate among one another and the user only communicates with the master to get the required job done. The master has to maintain a record of how the divided data has been distributed, how many workers have finished their work and returned a result, and the results themselves to be able to aggregate the data correctly. - -## Credits - -* [Master-Worker Pattern](https://docs.gigaspaces.com/sbp/master-worker-pattern.html) -* [The Master-Slave Design Pattern](https://www.cs.sjsu.edu/~pearce/oom/patterns/behavioral/masterslave.htm) diff --git a/master-worker/README.md b/master-worker/README.md new file mode 100644 index 000000000..60f3037e3 --- /dev/null +++ b/master-worker/README.md @@ -0,0 +1,149 @@ +--- +title: Master-Worker +category: Concurrency +language: en +tag: + - Multithreading + - Performance + - Scalability +--- + +## Also known as + +* Master-Slave +* Controller-Worker + +## Intent + +The Master-Worker pattern is designed to perform parallel computations through the division of labor between coordinating 'master' processes and multiple 'worker' processes. + +## Explanation + +Real World Example + +> Imagine a large restaurant kitchen where the head chef acts as the "master" and the line cooks serve as "workers." The head chef receives the orders from the dining area and breaks down each order into specific tasks, such as grilling meat, preparing salads, and cooking desserts. Each task is assigned to a different line cook based on their expertise and current workload. The line cooks work in parallel to prepare their portion of the order, while the head chef oversees the process, ensuring everything is prepared correctly and timely. Once each component of the order is ready, the head chef gathers all parts, gives them a final check, and then plates the dishes for service. This kitchen operation mimics the Master-Worker pattern by distributing and managing tasks to optimize efficiency and output. + +In Plain Words + +> The Master-Worker pattern involves a master process delegating tasks to multiple worker processes, which execute them concurrently and report back, optimizing parallel task processing and throughput. + +Wikipedia Says + +> Master–slave is a model of asymmetric communication or control where one device or process (the master) controls one or more other devices or processes (the slaves) and serves as their communication hub. In some systems, a master is selected from a group of eligible devices, with the other devices acting in the role of slaves. + +**Programmatic Example** + +The Master-Worker pattern is a design pattern that is used for parallel processing. It involves a master component that divides a task into subtasks and distributes them among worker components. The workers process the subtasks independently and return the results to the master, which then aggregates the results to form the final output. + +```java +// The MasterWorker class acts as the main entry point for the Master-Worker system. +public class MasterWorker { + private Master master; + + public MasterWorker(Master master) { + this.master = master; + } + + public Result getResult(Input input) { + return master.computeResult(input); + } +} +``` + +In this code, the `MasterWorker` class is initialized with a `Master` object. The `getResult` method is used to start the computation process. + +```java +// The Master class is responsible for dividing the work among the workers. +public abstract class Master { + protected List workers; + + public Master(List workers) { + this.workers = workers; + } + + public abstract Result computeResult(Input input); +} +``` + +The `Master` class has a list of `Worker` objects. The `computeResult` method is abstract and should be implemented in a subclass to define how the work is divided and how the results are aggregated. + +```java +// The Worker class is responsible for performing the actual computation. +public abstract class Worker extends Thread { + protected Input input; + + public void setInput(Input input) { + this.input = input; + } + + public abstract Result compute(); +} +``` + +The `Worker` class extends `Thread`, allowing it to perform computations in parallel. The `compute` method is abstract and should be implemented in a subclass to define the actual computation logic. + +```java +// The Input and Result classes are used to encapsulate the input data and the result data. +public abstract class Input { + public final T data; + + public Input(T data) { + this.data = data; + } + + public abstract List> divideData(int num); +} + +public abstract class Result { + public final T data; + + public Result(T data) { + this.data = data; + } +} +``` + +The `Input` class has a `divideData` method that is used to divide the input data into subtasks. The `Result` class simply encapsulates the result data. + +## Class diagram + +![Master-Worker](./etc/master-worker-pattern.urm.png "Master-Worker pattern class diagram") + +## Applicability + +* Suitable for scenarios where a task can be decomposed into smaller, independent tasks. +* Useful in applications requiring concurrent execution to enhance performance. +* Applicable in distributed computing where tasks need to be processed by multiple processors or machines. + +## Known Uses + +* Implemented in distributed systems to manage tasks across different computing resources. +* Used in server architectures to process multiple client requests simultaneously. +* Utilized in scientific computation frameworks where large datasets require parallel processing. + +## Consequences + +Benefits: + +* Enhances performance by parallelizing tasks. +* Increases responsiveness of systems handling large volumes of requests. +* Provides a clear separation of concerns between task coordination and task execution, simplifying design. + +Trade-offs: + +* Complexity in managing synchronization and state consistency between master and workers. +* Overhead of managing communication between master and workers, especially in distributed environments. + +## Related Patterns + +* Task Parallelism and Data Parallelism: Master-Worker utilizes these patterns to divide work into tasks or data segments. +* Producer-Consumer: Similar in structure but focuses on balancing production and consumption rates; Master-Worker is more about task distribution and aggregation. +* Pipeline: Both organize processing steps but Pipeline arranges them linearly whereas Master-Worker may not impose such a sequence. + +## Credits + +* [Distributed Systems: Principles and Paradigms](https://amzn.to/3UN2vbH) +* [Java Concurrency in Practice](https://amzn.to/4aRMruW) +* [Pattern-Oriented Software Architecture Volume 2: Patterns for Concurrent and Networked Objects](https://amzn.to/3UgC24V) +* [Master-Worker Pattern](https://docs.gigaspaces.com/sbp/master-worker-pattern.html) +* [The Master-Slave Design Pattern](https://www.cs.sjsu.edu/~pearce/oom/patterns/behavioral/masterslave.htm) diff --git a/master-worker-pattern/etc/master-worker-pattern.urm.png b/master-worker/etc/master-worker-pattern.urm.png similarity index 100% rename from master-worker-pattern/etc/master-worker-pattern.urm.png rename to master-worker/etc/master-worker-pattern.urm.png diff --git a/master-worker-pattern/etc/master-worker-pattern.urm.puml b/master-worker/etc/master-worker-pattern.urm.puml similarity index 100% rename from master-worker-pattern/etc/master-worker-pattern.urm.puml rename to master-worker/etc/master-worker-pattern.urm.puml diff --git a/master-worker-pattern/pom.xml b/master-worker/pom.xml similarity index 98% rename from master-worker-pattern/pom.xml rename to master-worker/pom.xml index 84d2e2e56..2661fea40 100644 --- a/master-worker-pattern/pom.xml +++ b/master-worker/pom.xml @@ -32,7 +32,7 @@ java-design-patterns 1.26.0-SNAPSHOT - master-worker-pattern + master-worker org.junit.jupiter diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/App.java b/master-worker/src/main/java/com/iluwatar/masterworker/App.java similarity index 100% rename from master-worker-pattern/src/main/java/com/iluwatar/masterworker/App.java rename to master-worker/src/main/java/com/iluwatar/masterworker/App.java diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/ArrayInput.java b/master-worker/src/main/java/com/iluwatar/masterworker/ArrayInput.java similarity index 100% rename from master-worker-pattern/src/main/java/com/iluwatar/masterworker/ArrayInput.java rename to master-worker/src/main/java/com/iluwatar/masterworker/ArrayInput.java diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/ArrayResult.java b/master-worker/src/main/java/com/iluwatar/masterworker/ArrayResult.java similarity index 100% rename from master-worker-pattern/src/main/java/com/iluwatar/masterworker/ArrayResult.java rename to master-worker/src/main/java/com/iluwatar/masterworker/ArrayResult.java diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/ArrayUtilityMethods.java b/master-worker/src/main/java/com/iluwatar/masterworker/ArrayUtilityMethods.java similarity index 100% rename from master-worker-pattern/src/main/java/com/iluwatar/masterworker/ArrayUtilityMethods.java rename to master-worker/src/main/java/com/iluwatar/masterworker/ArrayUtilityMethods.java diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/Input.java b/master-worker/src/main/java/com/iluwatar/masterworker/Input.java similarity index 100% rename from master-worker-pattern/src/main/java/com/iluwatar/masterworker/Input.java rename to master-worker/src/main/java/com/iluwatar/masterworker/Input.java diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/Result.java b/master-worker/src/main/java/com/iluwatar/masterworker/Result.java similarity index 100% rename from master-worker-pattern/src/main/java/com/iluwatar/masterworker/Result.java rename to master-worker/src/main/java/com/iluwatar/masterworker/Result.java diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/ArrayTransposeMasterWorker.java b/master-worker/src/main/java/com/iluwatar/masterworker/system/ArrayTransposeMasterWorker.java similarity index 100% rename from master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/ArrayTransposeMasterWorker.java rename to master-worker/src/main/java/com/iluwatar/masterworker/system/ArrayTransposeMasterWorker.java diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/MasterWorker.java b/master-worker/src/main/java/com/iluwatar/masterworker/system/MasterWorker.java similarity index 100% rename from master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/MasterWorker.java rename to master-worker/src/main/java/com/iluwatar/masterworker/system/MasterWorker.java diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemmaster/ArrayTransposeMaster.java b/master-worker/src/main/java/com/iluwatar/masterworker/system/systemmaster/ArrayTransposeMaster.java similarity index 100% rename from master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemmaster/ArrayTransposeMaster.java rename to master-worker/src/main/java/com/iluwatar/masterworker/system/systemmaster/ArrayTransposeMaster.java diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemmaster/Master.java b/master-worker/src/main/java/com/iluwatar/masterworker/system/systemmaster/Master.java similarity index 97% rename from master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemmaster/Master.java rename to master-worker/src/main/java/com/iluwatar/masterworker/system/systemmaster/Master.java index ac0cece38..800b63f71 100644 --- a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemmaster/Master.java +++ b/master-worker/src/main/java/com/iluwatar/masterworker/system/systemmaster/Master.java @@ -29,6 +29,7 @@ import com.iluwatar.masterworker.Result; import com.iluwatar.masterworker.system.systemworkers.Worker; import java.util.Hashtable; import java.util.List; +import lombok.Getter; /** * The abstract Master class which contains private fields numOfWorkers (number of workers), workers @@ -42,6 +43,7 @@ public abstract class Master { private final List workers; private final Hashtable> allResultData; private int expectedNumResults; + @Getter private Result finalResult; Master(int numOfWorkers) { @@ -52,10 +54,6 @@ public abstract class Master { this.finalResult = null; } - public Result getFinalResult() { - return this.finalResult; - } - Hashtable> getAllResultData() { return this.allResultData; } @@ -94,7 +92,7 @@ public abstract class Master { } public void receiveData(Result data, Worker w) { - //check if can receive..if yes: + // check if we can receive... if yes: collectResult(data, w.getWorkerId()); } diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemworkers/ArrayTransposeWorker.java b/master-worker/src/main/java/com/iluwatar/masterworker/system/systemworkers/ArrayTransposeWorker.java similarity index 100% rename from master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemworkers/ArrayTransposeWorker.java rename to master-worker/src/main/java/com/iluwatar/masterworker/system/systemworkers/ArrayTransposeWorker.java diff --git a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemworkers/Worker.java b/master-worker/src/main/java/com/iluwatar/masterworker/system/systemworkers/Worker.java similarity index 95% rename from master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemworkers/Worker.java rename to master-worker/src/main/java/com/iluwatar/masterworker/system/systemworkers/Worker.java index 6777dba27..a276fc540 100644 --- a/master-worker-pattern/src/main/java/com/iluwatar/masterworker/system/systemworkers/Worker.java +++ b/master-worker/src/main/java/com/iluwatar/masterworker/system/systemworkers/Worker.java @@ -27,6 +27,7 @@ package com.iluwatar.masterworker.system.systemworkers; import com.iluwatar.masterworker.Input; import com.iluwatar.masterworker.Result; import com.iluwatar.masterworker.system.systemmaster.Master; +import lombok.Getter; /** * The abstract Worker class which extends Thread class to enable parallel processing. Contains @@ -35,6 +36,7 @@ import com.iluwatar.masterworker.system.systemmaster.Master; public abstract class Worker extends Thread { private final Master master; + @Getter private final int workerId; private Input receivedData; @@ -44,16 +46,12 @@ public abstract class Worker extends Thread { this.receivedData = null; } - public int getWorkerId() { - return this.workerId; - } - Input getReceivedData() { return this.receivedData; } public void setReceivedData(Master m, Input i) { - //check if ready to receive..if yes: + // check if we are ready to receive... if yes: this.receivedData = i; } diff --git a/master-worker-pattern/src/test/java/com/iluwatar/masterworker/ArrayInputTest.java b/master-worker/src/test/java/com/iluwatar/masterworker/ArrayInputTest.java similarity index 100% rename from master-worker-pattern/src/test/java/com/iluwatar/masterworker/ArrayInputTest.java rename to master-worker/src/test/java/com/iluwatar/masterworker/ArrayInputTest.java diff --git a/master-worker-pattern/src/test/java/com/iluwatar/masterworker/ArrayUtilityMethodsTest.java b/master-worker/src/test/java/com/iluwatar/masterworker/ArrayUtilityMethodsTest.java similarity index 100% rename from master-worker-pattern/src/test/java/com/iluwatar/masterworker/ArrayUtilityMethodsTest.java rename to master-worker/src/test/java/com/iluwatar/masterworker/ArrayUtilityMethodsTest.java diff --git a/master-worker-pattern/src/test/java/com/iluwatar/masterworker/system/ArrayTransposeMasterWorkerTest.java b/master-worker/src/test/java/com/iluwatar/masterworker/system/ArrayTransposeMasterWorkerTest.java similarity index 100% rename from master-worker-pattern/src/test/java/com/iluwatar/masterworker/system/ArrayTransposeMasterWorkerTest.java rename to master-worker/src/test/java/com/iluwatar/masterworker/system/ArrayTransposeMasterWorkerTest.java diff --git a/master-worker-pattern/src/test/java/com/iluwatar/masterworker/system/systemworkers/ArrayTransposeWorkerTest.java b/master-worker/src/test/java/com/iluwatar/masterworker/system/systemworkers/ArrayTransposeWorkerTest.java similarity index 100% rename from master-worker-pattern/src/test/java/com/iluwatar/masterworker/system/systemworkers/ArrayTransposeWorkerTest.java rename to master-worker/src/test/java/com/iluwatar/masterworker/system/systemworkers/ArrayTransposeWorkerTest.java diff --git a/pom.xml b/pom.xml index f531b8553..f1703b889 100644 --- a/pom.xml +++ b/pom.xml @@ -162,7 +162,7 @@ ambassador acyclic-visitor collection-pipeline - master-worker-pattern + master-worker spatial-partition priority-queue commander