1.Master-Worker原理
1.1) Master-Worker模式是一种常见的并行设计模式之一,并行体现在一下两个方面:
1.1.1) Client端把待处理的任务交给Master,Master将这个任务拆分成多个子任务交给Worker线程进行处理,
此时Client不需要阻塞的等待Master的处理结果,可以去处理其他的事情
1.1.2) Master在汇总结果的时候,不用等到Worker把所有的子任务都完成,才一起去汇总处理结果,Master可
以一边先处理Worker已经处理完的子任务,Worker也可以继续处理未完成的子任务
1.2) Master-Worker工作图
1.3)Master-Worker模式的结构
1.3.1)Master-Worker模式是一种使用多线程技术进行数据处理的结果模型
1.3.2)Master线程为主线程,它维护了一个Worker线程队列,子任务队列和子结果集;Worker线程队列,
不断的从子任务队列中提取任务处理,并把处理结果写入子结果集中去
2.Master-Worker模式的简单代码实现
2.1)Master类
package com.roger.multi_thread;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* 主线程类
*/
public class Master {
//Worker线程队列
protected Map<String,Thread> workerThreadMap = new HashMap<>();
//子任务队列,Worker线程队列,不断从子任务队列中,获取待处理的任务进行执行
protected Queue<Object> subTaskWorkerQueue = new ConcurrentLinkedQueue<>();
//子任务的结果集存储容器
protected Map<String,Object> resultMap = new ConcurrentHashMap<>();
/**
* 构造Master的时候,需要一个Worker线程逻辑,
* 以及准备构造几个Worker线程进行子任务的处理
*/
public Master(Worker worker, int workerCount) {
worker.setSubTaskWorkerQueue(subTaskWorkerQueue);
worker.setResultMap(resultMap);
for(int i = 1; i<= workerCount; i ++){
workerThreadMap.put(Integer.toString(i),new Thread(worker));
}
}
/**
* 是否所有的任务都全部执行完成
* @return
* true 所有任务均已结束
* false 还有任务待处理中
*/
public boolean isComplete(){
for(Map.Entry<String,Thread> threadMap : workerThreadMap.entrySet()){
if(threadMap.getValue().getState() != Thread.State.TERMINATED){
return false;
}
}
return true;
}
/**
* 执行Worker子线程
*/
public void execute(){
for(Map.Entry<String,Thread> threadMap : workerThreadMap.entrySet()){
threadMap.getValue().start();
}
}
/**
* 提交子任务
* @param task
*/
public void submit(Object task){
subTaskWorkerQueue.add(task);
}
/**
* 获取所有子任务的处理结果集
* @return
*/
public Map<String, Object> getResultMap() {
return resultMap;
}
}
2.2)Worker线程类的代码
package com.roger.multi_thread;
import java.util.Map;
import java.util.Queue;
public abstract class Worker implements Runnable {
//Master线程中的所有子任务队列
public Queue<Object> subTaskWorkerQueue;
//Master线程中子任务处理的结果集
public Map<String,Object> resultMap;
@Override
public void run() {
//这里做非空判断的原因是保证代码的高可用
if(subTaskWorkerQueue == null || subTaskWorkerQueue.isEmpty()){
return;
}
for(;;){
//使用poll()方法处理,弹出并删除对首的对象
Object task = subTaskWorkerQueue.poll();
if(task == null){
//这个线程处理结束
break;
}
//处理子任务
Object result = bizProcess(task);
//这里没有做非空判断的原因,是这里地址传递
//在构造Master的时候,把Master中的子任务结果集
//传入Worker子线程中来
//if(resultMap == null){
//resultMap = new HashMap<>();
//}
//把处理结果存入结果集中去
resultMap.put(Integer.toString(task.hashCode()),result);
}
}
public void setSubTaskWorkerQueue(Queue<Object> subTaskWorkerQueue) {
this.subTaskWorkerQueue = subTaskWorkerQueue;
}
public void setResultMap(Map<String, Object> resultMap) {
this.resultMap = resultMap;
}
/**
* 子任务的业务处理结果
* 具体使用是通过重写bizProcess方法
* @param task
* @return
*/
public abstract Object bizProcess(Object task);
}
2.3) 具体业务实现类,继承Worker线程类,重写抽象方法 bizProcess(Object task)方法,以计算
1*1*1 + 2*2*2 + 3*3*3 + ... + 100*100+100 = ?
为例。
2.3.1) 分析这个任务,Master需要把这个任务拆分成100个子任务进行处理,每个任务只需处理1个自然数字的立方即可,
Master负责计算总和
2.3.2) 子任务的代码实现,继承Worker线程类,重写抽象方法 bizProcess方法
package com.roger.multi_thread;
public class PlusWorker extends Worker {
@Override
public Object bizProcess(Object task) {
Integer num = (Integer) task;
return num.intValue() * num.intValue()*num.intValue();
}
}
2.3.3) 启动类的实现代码
package com.roger.multi_thread;
import java.util.Map;
import java.util.Set;
/**
* Client向Master递交一个 1到100的立方和相加的任务
* 1*1*1 + 2*2*2 + 3*3*3 + ... + 100*100*100
*/
public class Bootstrap {
public static void main(String[] args) {
PlusWorker plusWorker = new PlusWorker();
Master master = new Master(plusWorker,5);
//Master线程拆分子任务,提交到Master管理的子任务队列中去
for(int i = 1; i <= 100; i ++){
master.submit(i);
}
//Master启动worker子线程,进行子任务的处理,并把子任务处理的结果汇总到
//Master管理的子任务结果集容器中去
master.execute();
//定义一个客户端提交的总任务处理结果的变量
int result = 0;
//汇总Master中管理的子任务结果集
Map<String, Object> resultMap = master.getResultMap();
//worker线程一边处理子任务,master线程一边汇总结果集
//结果集中已有Worker线程处理完的子任务结果集
//或者
//Master的子任务还没有全部处理完成
while (!resultMap.isEmpty() || !master.isComplete()){
//每次只处理一个key的值,循环处理,知道任务结束为止
Set<String> keySet = resultMap.keySet();
String key = null;
for(String k : keySet){
key = k;
break;
}
int reValue = 0;
if(key != null){
reValue = (Integer) resultMap.get(key);
//移除已经取出的子任务计算结果
resultMap.remove(key);
}
result = result + reValue;
}
System.out.println("1*1*1 + 2*2*2 + 3*3*3 + ... + 100*100*100 = " + result);
}
}
2.3.4)启动类运行结果: