master需要一個隊列存放任務、一個hashMap存放worker對象,這個對象不存在併發,一個結果集存放結果,因爲很多個worker在同時操作這個結果集,所以選擇使用concurrentHashMap;同樣的每一個worker都需要這個隊列和結果集。
Master-Worker模式是常用的並行模式之一,它的核心思想是,系統有兩個進程協作工作:Master進程,負責接收和分配任務;Worker進程,負責處理子任務。當Worker進程將子任務處理完成後,結果返回給Master進程,由Master進程做歸納彙總,最後得到最終的結果。
什麼是Master-Worker模式:
該模式的結構圖:
結構圖:
Worker:用於實際處理一個任務;
Master:任務的分配和最終結果的合成;
Main:啓動程序,調度開啓Master。
1、Master代碼:
package master_worker;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
public class Master {
// 1、承裝任務的集合
private ConcurrentLinkedQueue<Task> workQuene = new ConcurrentLinkedQueue<>();
// 2.使用hashMap裝所有的worker對象;
private HashMap<String, Thread> workers = new HashMap<>();
// 3、使用一個容器承裝每一個worker併發執行結果
private ConcurrentHashMap<String, Object> resultMap = new ConcurrentHashMap<>();
// 4、構造方法
public Master(Worker worker, int workerCount) {
// 每一個worker都需要有Master的引用用於任務的領取
worker.setWorkQuene(this.workQuene);
worker.setResultMap(this.resultMap);// 用於任務的提交
for (int i = 0; i <= workerCount; i++) {
// key每一個worker的名字,value線程執行對象
workers.put("子節點" + Integer.toString(i), new Thread(worker));
}
}
// 5、提交任務
public void submit(Task task) {
this.workQuene.add(task);
}
// 6、需要一個執行的方法(啓動應用程序,讓所有的worker工作)
public void execute() {
for (Map.Entry<String, Thread> me : workers.entrySet()) {
me.getValue().start();
}
}
//8、判斷線程是否執行完畢
public boolean isComplete() {
for (Map.Entry<String, Thread> me : workers.entrySet()) {
if(me.getValue().getState() != Thread.State.TERMINATED){
return false;
}
}
return true;
}
//返回結果集數據
public int getResult() {
int ret = 0;
for(Map.Entry<String, Object> me:resultMap.entrySet()){
//彙總的邏輯
ret+=(Integer)me.getValue();
}
return ret;
}
}
2、worker代碼:
package master_worker;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
public abstract class Worker implements Runnable{
ConcurrentHashMap<String, Object> resultMap;
ConcurrentLinkedQueue<Task> workQuene;
public void setResultMap(ConcurrentHashMap<String, Object> resultMap) {
this.resultMap=resultMap;
}
public void setWorkQuene(ConcurrentLinkedQueue<Task> workQuene) {
this.workQuene=workQuene;
}
@Override
public void run() {
while(true){
Task input = this.workQuene.poll();
if(input == null) {
break;
}
//以下是正真的業務處理
Object outPut = handle(input);
this.resultMap.put(Integer.toString(input.getId()), outPut);
}
}
//具體處理任務的代碼寫在子類中
public abstract Object handle(Task input);
/*//業務邏輯
private Object handle(Task input) {
Object outPut=null;
try {
//表示任務的耗時,可能是數據加工或者操作數據庫
Thread.sleep(500);
outPut = input.getPrice();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return outPut;
}*/
}
3、Main代碼:
package master_worker;
import java.util.Random;
public class Main {
public static void main(String[] args) {
Master master = new Master(new MyWork(), Runtime.getRuntime().availableProcessors());//Runtime.getRuntime().availableProcessors()當前機器可用的線程數
Random r = new Random();
for(int i=1;i<=100;i++){//100個任務
Task t=new Task();
t.setId(i);
t.setName("任務"+i);
t.setPrice(r.nextInt(1000));
master.submit(t);
}
master.execute();
long start = System.currentTimeMillis();
while(true){
if(master.isComplete()){
long end = System.currentTimeMillis()-start;
int ret = master.getResult();
System.out.println("最終結果:"+ret+",執行耗時:"+end);
break;
}
}
}
}
4、Task代碼:
package master_worker;
public class Task {
private int id;
private String name;
private int price;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
5、MyWorker代碼:
package master_worker;
public class MyWork extends Worker{
@Override
public Object handle(Task input) {
Object outPut=null;
try {
//表示任務的耗時,可能是數據加工或者操作數據庫
Thread.sleep(500);
outPut = input.getPrice();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return outPut;
}
}
將Worker抽象出來,具體的業務邏輯寫在子類中,可以擴張業務。