提交 7a25c574 编写于 作者: A AnaghaSasikumar 提交者: Ilkka Seppälä

Master worker pattern #799 (#831)

* master worker pattern

* Update App.java

* Adding new line to README.md

* Adding new line to pom.xml

* Adding new line to ArrayEquality.java

* Adding new line to Input.java

* Adding new line to Result.java

* Adding new line to ArrayTransposeMasterWorker.java

* Adding new line to ArrayTransposeMaster.java

* Adding new line to ArrayTransposeWorker.java

* Adding new line to Worker.java

* Adding new line to ArrayInputTest.java

* Adding new line ArrayTransposeMasterWorkerTest.java

* Adding new line to ArrayResult.java

* Review changes

* Update README.md
上级 55c75799
---
layout: pattern
title: Master-Worker
folder: master-worker-pattern
permalink: /patterns/master-worker-pattern/
categories: Centralised Parallel Processing
tags:
- Java
- Difficulty-Intermediate
---
## Also known as
> Master-slave or Map-reduce
## Intent
> Used for centralised parallel processing.
## 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
* [https://docs.gigaspaces.com/sbp/master-worker-pattern.html]
* [http://www.cs.sjsu.edu/~pearce/oom/patterns/behavioral/masterslave.htm]
<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.21.0-SNAPSHOT</version>
</parent>
<artifactId>master-worker-pattern</artifactId>
<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>
</dependencies>
</project>
/**
* The MIT License
* Copyright (c) 2014-2016 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.masterworker;
import com.iluwatar.masterworker.system.ArrayTransposeMasterWorker;
/**
* <p>The <b><em>Master-Worker</em></b> pattern is used when the problem at hand can be solved by dividing into
* multiple parts which need to go through the same computation and may need to be aggregated to get final result.
* 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 required job done.</p>
* <p>In our example, we have generic abstract classes {@link MasterWorker}, {@link Master} and {@link Worker} which
* have to be extended by the classes which will perform the specific job at hand (in this case finding transpose of
* matrix, done by {@link ArrayTransposeMasterWorker}, {@link ArrayTransposeMaster} and {@link ArrayTransposeWorker}).
* The Master class divides the work into parts to be given to the workers, collects the results from the workers and
* aggregates it when all workers have responded before returning the solution. The Worker class extends the Thread
* class to enable parallel processing, and does the work once the data has been received from the Master. The
* MasterWorker contains a reference to the Master class, gets the input from the App and passes it on to the Master.
* These 3 classes define the system which computes the result. We also have 2 abstract classes {@link Input} and
* {@link Result}, which contain the input data and result data respectively. The Input class also has an abstract
* method divideData which defines how the data is to be divided into segments. These classes are extended by
* {@link ArrayInput} and {@link ArrayResult}.</p>
*/
public class App {
/**
* Program entry point.
* @param args command line args
*/
public static void main(String[] args) {
ArrayTransposeMasterWorker mw = new ArrayTransposeMasterWorker();
int rows = 10;
int columns = 20;
int[][] inputMatrix = ArrayUtilityMethods.createRandomIntMatrix(rows,columns);
ArrayInput input = new ArrayInput(inputMatrix);
ArrayResult result = (ArrayResult) mw.getResult(input);
if (result != null) {
ArrayUtilityMethods.printMatrix(inputMatrix);
System.out.println("");
ArrayUtilityMethods.printMatrix(result.data);
} else {
System.out.println("Please enter non-zero input");
}
}
}
/**
* The MIT License
* Copyright (c) 2014-2016 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.masterworker;
import java.util.ArrayList;
import java.util.Arrays;
/**
*Class ArrayInput extends abstract class {@link Input} and contains data
*of type int[][].
*/
public class ArrayInput extends Input<int[][]> {
public ArrayInput(int[][] data) {
super(data);
}
static int[] makeDivisions(int[][] data, int num) {
int initialDivision = data.length / num; //equally dividing
int[] divisions = new int[num];
Arrays.fill(divisions, initialDivision);
if (initialDivision * num != data.length) {
int extra = data.length - initialDivision * num;
int l = 0;
//equally dividing extra among all parts
while (extra > 0) {
divisions[l] = divisions[l] + 1;
extra--;
if (l == num - 1) {
l = 0;
} else {
l++;
}
}
}
return divisions;
}
@Override
public ArrayList<Input> divideData(int num) {
if (this.data == null) {
return null;
} else {
int[] divisions = makeDivisions(this.data, num);
ArrayList<Input> result = new ArrayList<Input>(num);
int rowsDone = 0; //number of rows divided so far
for (int i = 0; i < num; i++) {
int rows = divisions[i];
if (rows != 0) {
int[][] divided = new int[rows][this.data[0].length];
for (int j = 0; j < rows; j++) {
divided[j] = this.data[rowsDone + j];
}
rowsDone += rows;
ArrayInput dividedInput = new ArrayInput(divided);
result.add(dividedInput);
} else {
break; //rest of divisions will also be 0
}
}
return result;
}
}
}
/**
* The MIT License
* Copyright (c) 2014-2016 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.masterworker;
/**
*Class ArrayResult extends abstract class {@link Result} and contains data
*of type int[][].
*/
public class ArrayResult extends Result<int[][]> {
public ArrayResult(int[][] data) {
super(data);
}
}
/**
* The MIT License
* Copyright (c) 2014-2016 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.masterworker;
import java.util.Random;
/**
*Class ArrayUtilityMethods has some utility methods for matrices and arrays.
*/
public class ArrayUtilityMethods {
/**
* Method arraysSame compares 2 arrays @param a1 and @param a2
* and @return whether their values are equal (boolean).
*/
public static boolean arraysSame(int[] a1, int[] a2) {
//compares if 2 arrays have the same value
if (a1.length != a2.length) {
return false;
} else {
boolean answer = false;
for (int i = 0; i < a1.length; i++) {
if (a1[i] == a2[i]) {
answer = true;
} else {
answer = false;
break;
}
}
return answer;
}
}
/**
* Method matricesSame compares 2 matrices @param m1 and @param m2
* and @return whether their values are equal (boolean).
*/
public static boolean matricesSame(int[][] m1, int[][] m2) {
if (m1.length != m2.length) {
return false;
} else {
boolean answer = false;
for (int i = 0; i < m1.length; i++) {
if (arraysSame(m1[i], m2[i])) {
answer = true;
} else {
answer = false;
break;
}
}
return answer;
}
}
/**
* Method createRandomIntMatrix creates a random matrix of size @param rows
* and @param columns @return it (int[][]).
*/
public static int[][] createRandomIntMatrix(int rows, int columns) {
int[][] matrix = new int[rows][columns];
Random rand = new Random();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
//filling cells in matrix
matrix[i][j] = rand.nextInt(10);
}
}
return matrix;
}
/**
* Method printMatrix prints input matrix @param matrix.
*/
public static void printMatrix(int[][] matrix) {
//prints out int[][]
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println("");
}
}
}
/**
* The MIT License
* Copyright (c) 2014-2016 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.masterworker;
import java.util.ArrayList;
/**
*The abstract Input class, having 1 public field which contains input data,
*and abstract method divideData.
* @param <T> T will be type of data.
*/
public abstract class Input<T> {
public final T data;
public Input(T data) {
this.data = data;
}
public abstract ArrayList<Input> divideData(int num);
}
/**
* The MIT License
* Copyright (c) 2014-2016 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.masterworker;
/**
*The abstract Result class, which contains 1 public field containing result
*data.
* @param <T> T will be type of data.
*/
public abstract class Result<T> {
public final T data;
public Result(T data) {
this.data = data;
}
}
/**
* The MIT License
* Copyright (c) 2014-2016 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.masterworker.system;
import com.iluwatar.masterworker.system.systemmaster.ArrayTransposeMaster;
import com.iluwatar.masterworker.system.systemmaster.Master;
/**
*Class ArrayTransposeMasterWorker extends abstract class {@link MasterWorker} and
*specifically solves the problem of finding transpose of input array.
*/
public class ArrayTransposeMasterWorker extends MasterWorker {
public ArrayTransposeMasterWorker() {
super(4);
}
@Override
Master setMaster(int numOfWorkers) {
return new ArrayTransposeMaster(numOfWorkers);
}
}
/**
* The MIT License
* Copyright (c) 2014-2016 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.masterworker.system;
import com.iluwatar.masterworker.Input;
import com.iluwatar.masterworker.Result;
import com.iluwatar.masterworker.system.systemmaster.Master;
/**
*The abstract MasterWorker class which contains reference to master.
*/
public abstract class MasterWorker {
private final Master master;
public MasterWorker(int numOfWorkers) {
this.master = setMaster(numOfWorkers);
}
abstract Master setMaster(int numOfWorkers);
public Result getResult(Input input) {
this.master.doWork(input);
return this.master.getFinalResult();
}
}
/**
* The MIT License
* Copyright (c) 2014-2016 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.masterworker.system.systemmaster;
import java.util.ArrayList;
import java.util.Enumeration;
import com.iluwatar.masterworker.ArrayResult;
import com.iluwatar.masterworker.system.systemworkers.ArrayTransposeWorker;
import com.iluwatar.masterworker.system.systemworkers.Worker;
/**
*Class ArrayTransposeMaster extends abstract class {@link Master} and contains
*definition of aggregateData, which will obtain final result from all
*data obtained and for setWorkers.
*/
public class ArrayTransposeMaster extends Master {
public ArrayTransposeMaster(int numOfWorkers) {
super(numOfWorkers);
}
@Override
ArrayList<Worker> setWorkers(int num) {
ArrayList<Worker> ws = new ArrayList<Worker>(num);
for (int i = 0; i < num ; i++) {
ws.add(new ArrayTransposeWorker(this, i + 1));
//i+1 will be id
}
return ws;
}
@Override
ArrayResult aggregateData() {
//number of rows in final result is number of rows in any of obtained results obtained from workers
int rows = ((ArrayResult) this.getAllResultData().get(this.getAllResultData().keys().nextElement())).data.length;
int columns = 0; //number of columns is sum of number of columns in all results obtained from workers
for (Enumeration<Integer> e = this.getAllResultData().keys(); e.hasMoreElements();) {
columns += ((ArrayResult) this.getAllResultData().get(e.nextElement())).data[0].length;
}
int[][] resultData = new int[rows][columns];
int columnsDone = 0; //columns aggregated so far
for (int i = 0; i < this.getExpectedNumResults(); i++) {
//result obtained from ith worker
int[][] work = ((ArrayResult) this.getAllResultData().get(this.getWorkers().get(i).getWorkerId())).data;
for (int m = 0; m < work.length; m++) {
//m = row number, n = columns number
for (int n = 0; n < work[0].length; n++) {
resultData[m][columnsDone + n] = work[m][n];
}
}
columnsDone += work[0].length;
}
return new ArrayResult(resultData);
}
}
/**
* The MIT License
* Copyright (c) 2014-2016 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.masterworker.system.systemmaster;
import java.util.ArrayList;
import java.util.Hashtable;
import com.iluwatar.masterworker.Input;
import com.iluwatar.masterworker.Result;
import com.iluwatar.masterworker.system.systemworkers.Worker;
/**
*The abstract Master class which contains private fields numOfWorkers
*(number of workers), workers (arraylist of workers), expectedNumResults
*(number of divisions of input data, same as expected number of results),
*allResultData (hashtable of results obtained from workers, mapped by
*their ids) and finalResult (aggregated from allResultData).
*/
public abstract class Master {
private final int numOfWorkers;
private final ArrayList<Worker> workers;
private int expectedNumResults;
private Hashtable<Integer, Result> allResultData;
private Result finalResult;
Master(int numOfWorkers) {
this.numOfWorkers = numOfWorkers;
this.workers = setWorkers(numOfWorkers);
this.expectedNumResults = 0;
this.allResultData = new Hashtable<Integer, Result>(numOfWorkers);
this.finalResult = null;
}
public Result getFinalResult() {
return this.finalResult;
}
Hashtable<Integer, Result> getAllResultData() {
return this.allResultData;
}
int getExpectedNumResults() {
return this.expectedNumResults;
}
ArrayList<Worker> getWorkers() {
return this.workers;
}
abstract ArrayList<Worker> setWorkers(int num);
public void doWork(Input input) {
divideWork(input);
}
private void divideWork(Input input) {
ArrayList<Input> dividedInput = input.divideData(numOfWorkers);
if (dividedInput != null) {
this.expectedNumResults = dividedInput.size();
for (int i = 0; i < this.expectedNumResults; i++) {
//ith division given to ith worker in this.workers
this.workers.get(i).setReceivedData(this, dividedInput.get(i));
this.workers.get(i).run();
}
}
}
public void receiveData(Result data, Worker w) {
//check if can receive..if yes:
collectResult(data, w.getWorkerId());
}
private void collectResult(Result data, int workerId) {
this.allResultData.put(workerId, data);
if (this.allResultData.size() == this.expectedNumResults) {
//all data received
this.finalResult = aggregateData();
}
}
abstract Result aggregateData();
}
/**
* The MIT License
* Copyright (c) 2014-2016 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.masterworker.system.systemworkers;
import com.iluwatar.masterworker.ArrayInput;
import com.iluwatar.masterworker.ArrayResult;
import com.iluwatar.masterworker.system.systemmaster.Master;
/**
*Class ArrayTransposeWorker extends abstract class {@link Worker} and defines method
*executeOperation(), to be performed on data received from master.
*/
public class ArrayTransposeWorker extends Worker {
public ArrayTransposeWorker(Master master, int id) {
super(master, id);
}
@Override
ArrayResult executeOperation() {
//number of rows in result matrix is equal to number of columns in input matrix and vice versa
int[][] resultData = new int[((ArrayInput) this.getReceivedData()).data[0].length]
[((ArrayInput) this.getReceivedData()).data.length];
for (int i = 0; i < ((ArrayInput) this.getReceivedData()).data.length; i++) {
for (int j = 0; j < ((ArrayInput) this.getReceivedData()).data[0].length; j++) {
//flipping element positions along diagonal
resultData[j][i] = ((ArrayInput) this.getReceivedData()).data[i][j];
}
}
return new ArrayResult(resultData);
}
}
/**
* The MIT License
* Copyright (c) 2014-2016 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.masterworker.system.systemworkers;
import com.iluwatar.masterworker.Input;
import com.iluwatar.masterworker.Result;
import com.iluwatar.masterworker.system.systemmaster.Master;
/**
*The abstract Worker class which extends Thread class to enable parallel
*processing. Contains fields master(holding reference to master), workerId
*(unique id) and receivedData(from master).
*/
public abstract class Worker extends Thread {
private final Master master;
private final int workerId;
private Input receivedData;
Worker(Master master, int id) {
this.master = master;
this.workerId = id;
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:
this.receivedData = i;
}
abstract Result executeOperation();
private void sendToMaster(Result data) {
this.master.receiveData(data, this);
}
public void run() { //from Thread class
Result work = executeOperation();
sendToMaster(work);
}
}
/**
* The MIT License
* Copyright (c) 2014-2016 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.masterworker;
import static org.junit.jupiter.api.Assertions.*;
import java.util.ArrayList;
import java.util.Random;
import org.junit.jupiter.api.Test;
/**
* Testing divideData method in {@link ArrayInput} class.
*/
class ArrayInputTest {
@Test
void divideDataTest() {
int rows = 10;
int columns = 10;
int[][] inputMatrix = new int[rows][columns];
Random rand = new Random();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
inputMatrix[i][j] = rand.nextInt(10);
}
}
ArrayInput i = new ArrayInput(inputMatrix);
ArrayList<Input> table = i.divideData(4);
int[][] division1 = new int[][] {inputMatrix[0], inputMatrix[1], inputMatrix[2]};
int[][] division2 = new int[][] {inputMatrix[3], inputMatrix[4], inputMatrix[5]};
int[][] division3 = new int[][] {inputMatrix[6], inputMatrix[7]};
int[][] division4 = new int[][] {inputMatrix[8], inputMatrix[9]};
assertTrue(ArrayUtilityMethods.matricesSame((int[][]) table.get(0).data, division1)
&& ArrayUtilityMethods.matricesSame((int[][]) table.get(1).data, division2)
&& ArrayUtilityMethods.matricesSame((int[][]) table.get(2).data, division3)
&& ArrayUtilityMethods.matricesSame((int[][]) table.get(3).data, division4));
}
}
package com.iluwatar.masterworker;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
/**
* Testing utility methods in {@link ArrayUtilityMethods} class.
*/
class ArrayUtilityMethodsTest {
@Test
void arraysSameTest() {
int[] arr1 = new int[] {1,4,2,6};
int[] arr2 = new int[] {1,4,2,6};
assertTrue(ArrayUtilityMethods.arraysSame(arr1, arr2));
}
@Test
void matricesSameTest() {
int[][] matrix1 = new int[][] {{1,4,2,6},{5,8,6,7}};
int[][] matrix2 = new int[][] {{1,4,2,6},{5,8,6,7}};
assertTrue(ArrayUtilityMethods.matricesSame(matrix1, matrix2));
}
}
/**
* The MIT License
* Copyright (c) 2014-2016 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.masterworker.system;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import com.iluwatar.masterworker.ArrayUtilityMethods;
import com.iluwatar.masterworker.ArrayInput;
import com.iluwatar.masterworker.ArrayResult;
/**
* Testing getResult method in {@link ArrayTransposeMasterWorker} class.
*/
class ArrayTransposeMasterWorkerTest {
@Test
void getResultTest() {
ArrayTransposeMasterWorker 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}};
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}};
ArrayInput i = new ArrayInput(matrix);
ArrayResult r = (ArrayResult) atmw.getResult(i);
assertTrue(ArrayUtilityMethods.matricesSame(r.data, matrixTranspose));
}
}
/**
* The MIT License
* Copyright (c) 2014-2016 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.masterworker.system.systemworkers;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import com.iluwatar.masterworker.ArrayUtilityMethods;
import com.iluwatar.masterworker.ArrayInput;
import com.iluwatar.masterworker.ArrayResult;
import com.iluwatar.masterworker.system.systemmaster.ArrayTransposeMaster;
/**
* Testing executeOperation method in {@link ArrayTransposeWorker} class.
*/
class ArrayTransposeWorkerTest {
@Test
void executeOperationTest() {
ArrayTransposeMaster atm = new ArrayTransposeMaster(1);
ArrayTransposeWorker atw = new ArrayTransposeWorker(atm, 1);
int[][] matrix = new int[][] {{2,4}, {3,5}};
int[][] matrixTranspose = new int[][] {{2,3}, {4,5}};
ArrayInput i = new ArrayInput(matrix);
atw.setReceivedData(atm, i);
ArrayResult r = atw.executeOperation();
assertTrue(ArrayUtilityMethods.matricesSame(r.data, matrixTranspose));
}
}
......@@ -164,6 +164,7 @@
<module>ambassador</module>
<module>acyclic-visitor</module>
<module>collection-pipeline</module>
<module>master-worker-pattern</module>
<module>spatial-partition</module>
</modules>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册