Java 11 migraiton: master-worker-pattern
This commit is contained in:
parent
e6c74a5fb9
commit
59e050b20b
@ -22,38 +22,39 @@
|
|||||||
THE SOFTWARE.
|
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">
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
<modelVersion>4.0.0</modelVersion>
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<parent>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>com.iluwatar</groupId>
|
<parent>
|
||||||
<artifactId>java-design-patterns</artifactId>
|
<groupId>com.iluwatar</groupId>
|
||||||
<version>1.23.0-SNAPSHOT</version>
|
<artifactId>java-design-patterns</artifactId>
|
||||||
</parent>
|
<version>1.23.0-SNAPSHOT</version>
|
||||||
<artifactId>master-worker-pattern</artifactId>
|
</parent>
|
||||||
<dependencies>
|
<artifactId>master-worker-pattern</artifactId>
|
||||||
<dependency>
|
<dependencies>
|
||||||
<groupId>org.junit.jupiter</groupId>
|
<dependency>
|
||||||
<artifactId>junit-jupiter-engine</artifactId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
<scope>test</scope>
|
<artifactId>junit-jupiter-engine</artifactId>
|
||||||
</dependency>
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<configuration>
|
<configuration>
|
||||||
<archive>
|
<archive>
|
||||||
<manifest>
|
<manifest>
|
||||||
<mainClass>com.iluwatar.masterworker.App</mainClass>
|
<mainClass>com.iluwatar.masterworker.App</mainClass>
|
||||||
</manifest>
|
</manifest>
|
||||||
</archive>
|
</archive>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
@ -34,27 +34,25 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>The <b><em>Master-Worker</em></b> pattern is used when the problem at hand can be solved by
|
* <p>The <b><em>Master-Worker</em></b> pattern is used when the problem at hand can be solved by
|
||||||
* dividing into
|
* dividing into multiple parts which need to go through the same computation and may need to be
|
||||||
* multiple parts which need to go through the same computation and may need to be aggregated to get
|
* aggregated to get final result. Parallel processing is performed using a system consisting of a
|
||||||
* final result. Parallel processing is performed using a system consisting of a master and some
|
* master and some number of workers, where a master divides the work among the workers, gets the
|
||||||
* number of workers, where a master divides the work among the workers, gets the result back from
|
* result back from them and assimilates all the results to give final result. The only
|
||||||
* them and assimilates all the results to give final result. The only communication is between the
|
* communication is between the master and the worker - none of the workers communicate among one
|
||||||
* master and the worker - none of the workers communicate among one another and the user only
|
* another and the user only communicates with the master to get required job done.</p>
|
||||||
* communicates with the master to get required job done.</p>
|
|
||||||
* <p>In our example, we have generic abstract classes {@link MasterWorker}, {@link Master} and
|
* <p>In our example, we have generic abstract classes {@link MasterWorker}, {@link Master} and
|
||||||
* {@link Worker} which
|
* {@link Worker} which have to be extended by the classes which will perform the specific job at
|
||||||
* have to be extended by the classes which will perform the specific job at hand (in this case
|
* hand (in this case finding transpose of matrix, done by {@link ArrayTransposeMasterWorker},
|
||||||
* finding transpose of matrix, done by {@link ArrayTransposeMasterWorker}, {@link
|
* {@link ArrayTransposeMaster} and {@link ArrayTransposeWorker}). The Master class divides the work
|
||||||
* ArrayTransposeMaster} and {@link ArrayTransposeWorker}). The Master class divides the work into
|
* into parts to be given to the workers, collects the results from the workers and aggregates it
|
||||||
* parts to be given to the workers, collects the results from the workers and aggregates it when
|
* when all workers have responded before returning the solution. The Worker class extends the
|
||||||
* all workers have responded before returning the solution. The Worker class extends the Thread
|
* Thread class to enable parallel processing, and does the work once the data has been received
|
||||||
* class to enable parallel processing, and does the work once the data has been received from the
|
* from the Master. The MasterWorker contains a reference to the Master class, gets the input from
|
||||||
* Master. The MasterWorker contains a reference to the Master class, gets the input from the App
|
* the App and passes it on to the Master. These 3 classes define the system which computes the
|
||||||
* and passes it on to the Master. These 3 classes define the system which computes the result. We
|
* result. We also have 2 abstract classes {@link Input} and {@link Result}, which contain the input
|
||||||
* also have 2 abstract classes {@link Input} and {@link Result}, which contain the input data and
|
* data and result data respectively. The Input class also has an abstract method divideData which
|
||||||
* result data respectively. The Input class also has an abstract method divideData which defines
|
* defines how the data is to be divided into segments. These classes are extended by {@link
|
||||||
* how the data is to be divided into segments. These classes are extended by {@link ArrayInput} and
|
* ArrayInput} and {@link ArrayResult}.</p>
|
||||||
* {@link ArrayResult}.</p>
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class App {
|
public class App {
|
||||||
@ -68,12 +66,12 @@ public class App {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
ArrayTransposeMasterWorker mw = new ArrayTransposeMasterWorker();
|
var mw = new ArrayTransposeMasterWorker();
|
||||||
int rows = 10;
|
var rows = 10;
|
||||||
int columns = 20;
|
var columns = 20;
|
||||||
int[][] inputMatrix = ArrayUtilityMethods.createRandomIntMatrix(rows, columns);
|
var inputMatrix = ArrayUtilityMethods.createRandomIntMatrix(rows, columns);
|
||||||
ArrayInput input = new ArrayInput(inputMatrix);
|
var input = new ArrayInput(inputMatrix);
|
||||||
ArrayResult result = (ArrayResult) mw.getResult(input);
|
var result = (ArrayResult) mw.getResult(input);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
ArrayUtilityMethods.printMatrix(inputMatrix);
|
ArrayUtilityMethods.printMatrix(inputMatrix);
|
||||||
ArrayUtilityMethods.printMatrix(result.data);
|
ArrayUtilityMethods.printMatrix(result.data);
|
||||||
|
@ -25,6 +25,7 @@ package com.iluwatar.masterworker;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ArrayInput extends abstract class {@link Input} and contains data of type int[][].
|
* Class ArrayInput extends abstract class {@link Input} and contains data of type int[][].
|
||||||
@ -37,12 +38,12 @@ public class ArrayInput extends Input<int[][]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int[] makeDivisions(int[][] data, int num) {
|
static int[] makeDivisions(int[][] data, int num) {
|
||||||
int initialDivision = data.length / num; //equally dividing
|
var initialDivision = data.length / num; //equally dividing
|
||||||
int[] divisions = new int[num];
|
var divisions = new int[num];
|
||||||
Arrays.fill(divisions, initialDivision);
|
Arrays.fill(divisions, initialDivision);
|
||||||
if (initialDivision * num != data.length) {
|
if (initialDivision * num != data.length) {
|
||||||
int extra = data.length - initialDivision * num;
|
var extra = data.length - initialDivision * num;
|
||||||
int l = 0;
|
var l = 0;
|
||||||
//equally dividing extra among all parts
|
//equally dividing extra among all parts
|
||||||
while (extra > 0) {
|
while (extra > 0) {
|
||||||
divisions[l] = divisions[l] + 1;
|
divisions[l] = divisions[l] + 1;
|
||||||
@ -58,22 +59,20 @@ public class ArrayInput extends Input<int[][]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ArrayList<Input> divideData(int num) {
|
public List<Input<int[][]>> divideData(int num) {
|
||||||
if (this.data == null) {
|
if (this.data == null) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
int[] divisions = makeDivisions(this.data, num);
|
var divisions = makeDivisions(this.data, num);
|
||||||
ArrayList<Input> result = new ArrayList<Input>(num);
|
var result = new ArrayList<Input<int[][]>>(num);
|
||||||
int rowsDone = 0; //number of rows divided so far
|
var rowsDone = 0; //number of rows divided so far
|
||||||
for (int i = 0; i < num; i++) {
|
for (var i = 0; i < num; i++) {
|
||||||
int rows = divisions[i];
|
var rows = divisions[i];
|
||||||
if (rows != 0) {
|
if (rows != 0) {
|
||||||
int[][] divided = new int[rows][this.data[0].length];
|
var divided = new int[rows][this.data[0].length];
|
||||||
for (int j = 0; j < rows; j++) {
|
System.arraycopy(this.data, rowsDone, divided, 0, rows);
|
||||||
divided[j] = this.data[rowsDone + j];
|
|
||||||
}
|
|
||||||
rowsDone += rows;
|
rowsDone += rows;
|
||||||
ArrayInput dividedInput = new ArrayInput(divided);
|
var dividedInput = new ArrayInput(divided);
|
||||||
result.add(dividedInput);
|
result.add(dividedInput);
|
||||||
} else {
|
} else {
|
||||||
break; //rest of divisions will also be 0
|
break; //rest of divisions will also be 0
|
||||||
|
@ -47,8 +47,8 @@ public class ArrayUtilityMethods {
|
|||||||
if (a1.length != a2.length) {
|
if (a1.length != a2.length) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
boolean answer = false;
|
var answer = false;
|
||||||
for (int i = 0; i < a1.length; i++) {
|
for (var i = 0; i < a1.length; i++) {
|
||||||
if (a1[i] == a2[i]) {
|
if (a1[i] == a2[i]) {
|
||||||
answer = true;
|
answer = true;
|
||||||
} else {
|
} else {
|
||||||
@ -69,8 +69,8 @@ public class ArrayUtilityMethods {
|
|||||||
if (m1.length != m2.length) {
|
if (m1.length != m2.length) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
boolean answer = false;
|
var answer = false;
|
||||||
for (int i = 0; i < m1.length; i++) {
|
for (var i = 0; i < m1.length; i++) {
|
||||||
if (arraysSame(m1[i], m2[i])) {
|
if (arraysSame(m1[i], m2[i])) {
|
||||||
answer = true;
|
answer = true;
|
||||||
} else {
|
} else {
|
||||||
@ -88,9 +88,9 @@ public class ArrayUtilityMethods {
|
|||||||
* @return it (int[][]).
|
* @return it (int[][]).
|
||||||
*/
|
*/
|
||||||
public static int[][] createRandomIntMatrix(int rows, int columns) {
|
public static int[][] createRandomIntMatrix(int rows, int columns) {
|
||||||
int[][] matrix = new int[rows][columns];
|
var matrix = new int[rows][columns];
|
||||||
for (int i = 0; i < rows; i++) {
|
for (var i = 0; i < rows; i++) {
|
||||||
for (int j = 0; j < columns; j++) {
|
for (var j = 0; j < columns; j++) {
|
||||||
//filling cells in matrix
|
//filling cells in matrix
|
||||||
matrix[i][j] = RANDOM.nextInt(10);
|
matrix[i][j] = RANDOM.nextInt(10);
|
||||||
}
|
}
|
||||||
@ -104,9 +104,9 @@ public class ArrayUtilityMethods {
|
|||||||
|
|
||||||
public static void printMatrix(int[][] matrix) {
|
public static void printMatrix(int[][] matrix) {
|
||||||
//prints out int[][]
|
//prints out int[][]
|
||||||
for (int i = 0; i < matrix.length; i++) {
|
for (var ints : matrix) {
|
||||||
for (int j = 0; j < matrix[0].length; j++) {
|
for (var j = 0; j < matrix[0].length; j++) {
|
||||||
LOGGER.info(matrix[i][j] + " ");
|
LOGGER.info(ints[j] + " ");
|
||||||
}
|
}
|
||||||
LOGGER.info("");
|
LOGGER.info("");
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
package com.iluwatar.masterworker;
|
package com.iluwatar.masterworker;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The abstract Input class, having 1 public field which contains input data, and abstract method
|
* The abstract Input class, having 1 public field which contains input data, and abstract method
|
||||||
@ -40,5 +40,5 @@ public abstract class Input<T> {
|
|||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract ArrayList<Input> divideData(int num);
|
public abstract List<Input<T>> divideData(int num);
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ public abstract class MasterWorker {
|
|||||||
|
|
||||||
abstract Master setMaster(int numOfWorkers);
|
abstract Master setMaster(int numOfWorkers);
|
||||||
|
|
||||||
public Result getResult(Input input) {
|
public Result<?> getResult(Input<?> input) {
|
||||||
this.master.doWork(input);
|
this.master.doWork(input);
|
||||||
return this.master.getFinalResult();
|
return this.master.getFinalResult();
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,8 @@ import com.iluwatar.masterworker.ArrayResult;
|
|||||||
import com.iluwatar.masterworker.system.systemworkers.ArrayTransposeWorker;
|
import com.iluwatar.masterworker.system.systemworkers.ArrayTransposeWorker;
|
||||||
import com.iluwatar.masterworker.system.systemworkers.Worker;
|
import com.iluwatar.masterworker.system.systemworkers.Worker;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Enumeration;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ArrayTransposeMaster extends abstract class {@link Master} and contains definition of
|
* Class ArrayTransposeMaster extends abstract class {@link Master} and contains definition of
|
||||||
@ -41,35 +42,33 @@ public class ArrayTransposeMaster extends Master {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
ArrayList<Worker> setWorkers(int num) {
|
ArrayList<Worker> setWorkers(int num) {
|
||||||
ArrayList<Worker> ws = new ArrayList<Worker>(num);
|
//i+1 will be id
|
||||||
for (int i = 0; i < num; i++) {
|
return IntStream.range(0, num)
|
||||||
ws.add(new ArrayTransposeWorker(this, i + 1));
|
.mapToObj(i -> new ArrayTransposeWorker(this, i + 1))
|
||||||
//i+1 will be id
|
.collect(Collectors.toCollection(() -> new ArrayList<>(num)));
|
||||||
}
|
|
||||||
return ws;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
ArrayResult aggregateData() {
|
ArrayResult aggregateData() {
|
||||||
// number of rows in final result is number of rows in any of obtained results from workers
|
// number of rows in final result is number of rows in any of obtained results from workers
|
||||||
int rows = ((ArrayResult) this.getAllResultData()
|
var allResultData = this.getAllResultData();
|
||||||
.get(this.getAllResultData().keys().nextElement())).data.length;
|
var rows = ((ArrayResult) allResultData.elements().nextElement()).data.length;
|
||||||
int columns =
|
var elements = allResultData.elements();
|
||||||
0; //number of columns is sum of number of columns in all results obtained from workers
|
var columns = 0; // columns = sum of number of columns in all results obtained from workers
|
||||||
for (Enumeration<Integer> e = this.getAllResultData().keys(); e.hasMoreElements(); ) {
|
while (elements.hasMoreElements()) {
|
||||||
columns += ((ArrayResult) this.getAllResultData().get(e.nextElement())).data[0].length;
|
columns += ((ArrayResult) elements.nextElement()).data[0].length;
|
||||||
}
|
}
|
||||||
int[][] resultData = new int[rows][columns];
|
var resultData = new int[rows][columns];
|
||||||
int columnsDone = 0; //columns aggregated so far
|
var columnsDone = 0; //columns aggregated so far
|
||||||
for (int i = 0; i < this.getExpectedNumResults(); i++) {
|
var workers = this.getWorkers();
|
||||||
|
for (var i = 0; i < this.getExpectedNumResults(); i++) {
|
||||||
//result obtained from ith worker
|
//result obtained from ith worker
|
||||||
int[][] work =
|
var worker = workers.get(i);
|
||||||
((ArrayResult) this.getAllResultData().get(this.getWorkers().get(i).getWorkerId())).data;
|
var workerId = worker.getWorkerId();
|
||||||
for (int m = 0; m < work.length; m++) {
|
var work = ((ArrayResult) allResultData.get(workerId)).data;
|
||||||
|
for (var m = 0; m < work.length; m++) {
|
||||||
//m = row number, n = columns number
|
//m = row number, n = columns number
|
||||||
for (int n = 0; n < work[0].length; n++) {
|
System.arraycopy(work[m], 0, resultData[m], columnsDone, work[0].length);
|
||||||
resultData[m][columnsDone + n] = work[m][n];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
columnsDone += work[0].length;
|
columnsDone += work[0].length;
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,9 @@ package com.iluwatar.masterworker.system.systemmaster;
|
|||||||
import com.iluwatar.masterworker.Input;
|
import com.iluwatar.masterworker.Input;
|
||||||
import com.iluwatar.masterworker.Result;
|
import com.iluwatar.masterworker.Result;
|
||||||
import com.iluwatar.masterworker.system.systemworkers.Worker;
|
import com.iluwatar.masterworker.system.systemworkers.Worker;
|
||||||
import java.util.ArrayList;
|
import java.util.Dictionary;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The abstract Master class which contains private fields numOfWorkers (number of workers), workers
|
* The abstract Master class which contains private fields numOfWorkers (number of workers), workers
|
||||||
@ -38,24 +39,24 @@ import java.util.Hashtable;
|
|||||||
|
|
||||||
public abstract class Master {
|
public abstract class Master {
|
||||||
private final int numOfWorkers;
|
private final int numOfWorkers;
|
||||||
private final ArrayList<Worker> workers;
|
private final List<Worker> workers;
|
||||||
|
private final Dictionary<Integer, Result<?>> allResultData;
|
||||||
private int expectedNumResults;
|
private int expectedNumResults;
|
||||||
private Hashtable<Integer, Result> allResultData;
|
private Result<?> finalResult;
|
||||||
private Result finalResult;
|
|
||||||
|
|
||||||
Master(int numOfWorkers) {
|
Master(int numOfWorkers) {
|
||||||
this.numOfWorkers = numOfWorkers;
|
this.numOfWorkers = numOfWorkers;
|
||||||
this.workers = setWorkers(numOfWorkers);
|
this.workers = setWorkers(numOfWorkers);
|
||||||
this.expectedNumResults = 0;
|
this.expectedNumResults = 0;
|
||||||
this.allResultData = new Hashtable<Integer, Result>(numOfWorkers);
|
this.allResultData = new Hashtable<>(numOfWorkers);
|
||||||
this.finalResult = null;
|
this.finalResult = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Result getFinalResult() {
|
public Result<?> getFinalResult() {
|
||||||
return this.finalResult;
|
return this.finalResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
Hashtable<Integer, Result> getAllResultData() {
|
Dictionary<Integer, Result<?>> getAllResultData() {
|
||||||
return this.allResultData;
|
return this.allResultData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,21 +64,21 @@ public abstract class Master {
|
|||||||
return this.expectedNumResults;
|
return this.expectedNumResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayList<Worker> getWorkers() {
|
List<Worker> getWorkers() {
|
||||||
return this.workers;
|
return this.workers;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract ArrayList<Worker> setWorkers(int num);
|
abstract List<Worker> setWorkers(int num);
|
||||||
|
|
||||||
public void doWork(Input input) {
|
public void doWork(Input<?> input) {
|
||||||
divideWork(input);
|
divideWork(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void divideWork(Input input) {
|
private void divideWork(Input<?> input) {
|
||||||
ArrayList<Input> dividedInput = input.divideData(numOfWorkers);
|
List<? extends Input<?>> dividedInput = input.divideData(numOfWorkers);
|
||||||
if (dividedInput != null) {
|
if (dividedInput != null) {
|
||||||
this.expectedNumResults = dividedInput.size();
|
this.expectedNumResults = dividedInput.size();
|
||||||
for (int i = 0; i < this.expectedNumResults; i++) {
|
for (var i = 0; i < this.expectedNumResults; i++) {
|
||||||
//ith division given to ith worker in this.workers
|
//ith division given to ith worker in this.workers
|
||||||
this.workers.get(i).setReceivedData(this, dividedInput.get(i));
|
this.workers.get(i).setReceivedData(this, dividedInput.get(i));
|
||||||
this.workers.get(i).run();
|
this.workers.get(i).run();
|
||||||
@ -85,12 +86,12 @@ public abstract class Master {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void receiveData(Result data, Worker w) {
|
public void receiveData(Result<?> data, Worker w) {
|
||||||
//check if can receive..if yes:
|
//check if can receive..if yes:
|
||||||
collectResult(data, w.getWorkerId());
|
collectResult(data, w.getWorkerId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void collectResult(Result data, int workerId) {
|
private void collectResult(Result<?> data, int workerId) {
|
||||||
this.allResultData.put(workerId, data);
|
this.allResultData.put(workerId, data);
|
||||||
if (this.allResultData.size() == this.expectedNumResults) {
|
if (this.allResultData.size() == this.expectedNumResults) {
|
||||||
//all data received
|
//all data received
|
||||||
@ -98,5 +99,5 @@ public abstract class Master {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract Result aggregateData();
|
abstract Result<?> aggregateData();
|
||||||
}
|
}
|
||||||
|
@ -41,12 +41,12 @@ public class ArrayTransposeWorker extends Worker {
|
|||||||
@Override
|
@Override
|
||||||
ArrayResult executeOperation() {
|
ArrayResult executeOperation() {
|
||||||
//number of rows in result matrix is equal to number of columns in input matrix and vice versa
|
//number of rows in result matrix is equal to number of columns in input matrix and vice versa
|
||||||
ArrayInput arrayInput = (ArrayInput) this.getReceivedData();
|
var arrayInput = (ArrayInput) this.getReceivedData();
|
||||||
final int rows = arrayInput.data[0].length;
|
final var rows = arrayInput.data[0].length;
|
||||||
final int cols = arrayInput.data.length;
|
final var cols = arrayInput.data.length;
|
||||||
int[][] resultData = new int[rows][cols];
|
var resultData = new int[rows][cols];
|
||||||
for (int i = 0; i < cols; i++) {
|
for (var i = 0; i < cols; i++) {
|
||||||
for (int j = 0; j < rows; j++) {
|
for (var j = 0; j < rows; j++) {
|
||||||
//flipping element positions along diagonal
|
//flipping element positions along diagonal
|
||||||
resultData[j][i] = arrayInput.data[i][j];
|
resultData[j][i] = arrayInput.data[i][j];
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ import com.iluwatar.masterworker.system.systemmaster.Master;
|
|||||||
public abstract class Worker extends Thread {
|
public abstract class Worker extends Thread {
|
||||||
private final Master master;
|
private final Master master;
|
||||||
private final int workerId;
|
private final int workerId;
|
||||||
private Input receivedData;
|
private Input<?> receivedData;
|
||||||
|
|
||||||
Worker(Master master, int id) {
|
Worker(Master master, int id) {
|
||||||
this.master = master;
|
this.master = master;
|
||||||
@ -47,23 +47,23 @@ public abstract class Worker extends Thread {
|
|||||||
return this.workerId;
|
return this.workerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
Input getReceivedData() {
|
Input<?> getReceivedData() {
|
||||||
return this.receivedData;
|
return this.receivedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setReceivedData(Master m, Input i) {
|
public void setReceivedData(Master m, Input<?> i) {
|
||||||
//check if ready to receive..if yes:
|
//check if ready to receive..if yes:
|
||||||
this.receivedData = i;
|
this.receivedData = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract Result executeOperation();
|
abstract Result<?> executeOperation();
|
||||||
|
|
||||||
private void sendToMaster(Result data) {
|
private void sendToMaster(Result<?> data) {
|
||||||
this.master.receiveData(data, this);
|
this.master.receiveData(data, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() { //from Thread class
|
public void run() { //from Thread class
|
||||||
Result work = executeOperation();
|
var work = executeOperation();
|
||||||
sendToMaster(work);
|
sendToMaster(work);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,38 +23,39 @@
|
|||||||
|
|
||||||
package com.iluwatar.masterworker;
|
package com.iluwatar.masterworker;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static com.iluwatar.masterworker.ArrayUtilityMethods.matricesSame;
|
||||||
import java.util.ArrayList;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Testing divideData method in {@link ArrayInput} class.
|
* Testing divideData method in {@link ArrayInput} class.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ArrayInputTest {
|
class ArrayInputTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void divideDataTest() {
|
void divideDataTest() {
|
||||||
int rows = 10;
|
var rows = 10;
|
||||||
int columns = 10;
|
var columns = 10;
|
||||||
int[][] inputMatrix = new int[rows][columns];
|
var inputMatrix = new int[rows][columns];
|
||||||
Random rand = new Random();
|
var rand = new Random();
|
||||||
for (int i = 0; i < rows; i++) {
|
for (var i = 0; i < rows; i++) {
|
||||||
for (int j = 0; j < columns; j++) {
|
for (var j = 0; j < columns; j++) {
|
||||||
inputMatrix[i][j] = rand.nextInt(10);
|
inputMatrix[i][j] = rand.nextInt(10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ArrayInput i = new ArrayInput(inputMatrix);
|
var i = new ArrayInput(inputMatrix);
|
||||||
ArrayList<Input> table = i.divideData(4);
|
var table = i.divideData(4);
|
||||||
int[][] division1 = new int[][] {inputMatrix[0], inputMatrix[1], inputMatrix[2]};
|
var division1 = new int[][]{inputMatrix[0], inputMatrix[1], inputMatrix[2]};
|
||||||
int[][] division2 = new int[][] {inputMatrix[3], inputMatrix[4], inputMatrix[5]};
|
var division2 = new int[][]{inputMatrix[3], inputMatrix[4], inputMatrix[5]};
|
||||||
int[][] division3 = new int[][] {inputMatrix[6], inputMatrix[7]};
|
var division3 = new int[][]{inputMatrix[6], inputMatrix[7]};
|
||||||
int[][] division4 = new int[][] {inputMatrix[8], inputMatrix[9]};
|
var division4 = new int[][]{inputMatrix[8], inputMatrix[9]};
|
||||||
assertTrue(ArrayUtilityMethods.matricesSame((int[][]) table.get(0).data, division1)
|
assertTrue(matricesSame(table.get(0).data, division1)
|
||||||
&& ArrayUtilityMethods.matricesSame((int[][]) table.get(1).data, division2)
|
&& matricesSame(table.get(1).data, division2)
|
||||||
&& ArrayUtilityMethods.matricesSame((int[][]) table.get(2).data, division3)
|
&& matricesSame(table.get(2).data, division3)
|
||||||
&& ArrayUtilityMethods.matricesSame((int[][]) table.get(3).data, division4));
|
&& matricesSame(table.get(3).data, division4));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,27 +23,27 @@
|
|||||||
|
|
||||||
package com.iluwatar.masterworker;
|
package com.iluwatar.masterworker;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Testing utility methods in {@link ArrayUtilityMethods} class.
|
* Testing utility methods in {@link ArrayUtilityMethods} class.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ArrayUtilityMethodsTest {
|
class ArrayUtilityMethodsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void arraysSameTest() {
|
void arraysSameTest() {
|
||||||
int[] arr1 = new int[] {1,4,2,6};
|
var arr1 = new int[]{1, 4, 2, 6};
|
||||||
int[] arr2 = new int[] {1,4,2,6};
|
var arr2 = new int[]{1, 4, 2, 6};
|
||||||
assertTrue(ArrayUtilityMethods.arraysSame(arr1, arr2));
|
assertTrue(ArrayUtilityMethods.arraysSame(arr1, arr2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void matricesSameTest() {
|
void matricesSameTest() {
|
||||||
int[][] matrix1 = new int[][] {{1,4,2,6},{5,8,6,7}};
|
var matrix1 = new int[][]{{1, 4, 2, 6}, {5, 8, 6, 7}};
|
||||||
int[][] matrix2 = new int[][] {{1,4,2,6},{5,8,6,7}};
|
var matrix2 = new int[][]{{1, 4, 2, 6}, {5, 8, 6, 7}};
|
||||||
assertTrue(ArrayUtilityMethods.matricesSame(matrix1, matrix2));
|
assertTrue(ArrayUtilityMethods.matricesSame(matrix1, matrix2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,25 +23,38 @@
|
|||||||
|
|
||||||
package com.iluwatar.masterworker.system;
|
package com.iluwatar.masterworker.system;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import com.iluwatar.masterworker.ArrayUtilityMethods;
|
|
||||||
import com.iluwatar.masterworker.ArrayInput;
|
import com.iluwatar.masterworker.ArrayInput;
|
||||||
import com.iluwatar.masterworker.ArrayResult;
|
import com.iluwatar.masterworker.ArrayResult;
|
||||||
|
import com.iluwatar.masterworker.ArrayUtilityMethods;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Testing getResult method in {@link ArrayTransposeMasterWorker} class.
|
* Testing getResult method in {@link ArrayTransposeMasterWorker} class.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ArrayTransposeMasterWorkerTest {
|
class ArrayTransposeMasterWorkerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getResultTest() {
|
void getResultTest() {
|
||||||
ArrayTransposeMasterWorker atmw = new ArrayTransposeMasterWorker();
|
var atmw = new ArrayTransposeMasterWorker();
|
||||||
int[][] matrix = new int[][] {{1,2,3,4,5}, {1,2,3,4,5}, {1,2,3,4,5}, {1,2,3,4,5}, {1,2,3,4,5}};
|
var matrix = new int[][]{
|
||||||
int[][] matrixTranspose = new int[][] {{1,1,1,1,1}, {2,2,2,2,2}, {3,3,3,3,3}, {4,4,4,4,4}, {5,5,5,5,5}};
|
{1, 2, 3, 4, 5},
|
||||||
ArrayInput i = new ArrayInput(matrix);
|
{1, 2, 3, 4, 5},
|
||||||
ArrayResult r = (ArrayResult) atmw.getResult(i);
|
{1, 2, 3, 4, 5},
|
||||||
|
{1, 2, 3, 4, 5},
|
||||||
|
{1, 2, 3, 4, 5}
|
||||||
|
};
|
||||||
|
var matrixTranspose = new int[][]{
|
||||||
|
{1, 1, 1, 1, 1},
|
||||||
|
{2, 2, 2, 2, 2},
|
||||||
|
{3, 3, 3, 3, 3},
|
||||||
|
{4, 4, 4, 4, 4},
|
||||||
|
{5, 5, 5, 5, 5}
|
||||||
|
};
|
||||||
|
var i = new ArrayInput(matrix);
|
||||||
|
var r = (ArrayResult) atmw.getResult(i);
|
||||||
assertTrue(ArrayUtilityMethods.matricesSame(r.data, matrixTranspose));
|
assertTrue(ArrayUtilityMethods.matricesSame(r.data, matrixTranspose));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,29 +23,29 @@
|
|||||||
|
|
||||||
package com.iluwatar.masterworker.system.systemworkers;
|
package com.iluwatar.masterworker.system.systemworkers;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import com.iluwatar.masterworker.ArrayUtilityMethods;
|
|
||||||
import com.iluwatar.masterworker.ArrayInput;
|
import com.iluwatar.masterworker.ArrayInput;
|
||||||
import com.iluwatar.masterworker.ArrayResult;
|
import com.iluwatar.masterworker.ArrayUtilityMethods;
|
||||||
import com.iluwatar.masterworker.system.systemmaster.ArrayTransposeMaster;
|
import com.iluwatar.masterworker.system.systemmaster.ArrayTransposeMaster;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Testing executeOperation method in {@link ArrayTransposeWorker} class.
|
* Testing executeOperation method in {@link ArrayTransposeWorker} class.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ArrayTransposeWorkerTest {
|
class ArrayTransposeWorkerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void executeOperationTest() {
|
void executeOperationTest() {
|
||||||
ArrayTransposeMaster atm = new ArrayTransposeMaster(1);
|
var atm = new ArrayTransposeMaster(1);
|
||||||
ArrayTransposeWorker atw = new ArrayTransposeWorker(atm, 1);
|
var atw = new ArrayTransposeWorker(atm, 1);
|
||||||
int[][] matrix = new int[][] {{2,4}, {3,5}};
|
var matrix = new int[][]{{2, 4}, {3, 5}};
|
||||||
int[][] matrixTranspose = new int[][] {{2,3}, {4,5}};
|
var matrixTranspose = new int[][]{{2, 3}, {4, 5}};
|
||||||
ArrayInput i = new ArrayInput(matrix);
|
var i = new ArrayInput(matrix);
|
||||||
atw.setReceivedData(atm, i);
|
atw.setReceivedData(atm, i);
|
||||||
ArrayResult r = atw.executeOperation();
|
var r = atw.executeOperation();
|
||||||
assertTrue(ArrayUtilityMethods.matricesSame(r.data, matrixTranspose));
|
assertTrue(ArrayUtilityMethods.matricesSame(r.data, matrixTranspose));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user