Master-Worker设计模式介绍
Master-Worker模式是常用的并行设计模式。核心思想是,系统由两个角色组成,Master和Worker,Master负责接收和分配任务,Worker负责处理子任务。任务处理过程中,Master还负责监督任务进展和Worker的健康状态;Master将接收Client提交的任务,并将任务的进展汇总反馈给Client。各角色关系如下图

Master-Worker模式满足于可以将大任务划分为小任务的场景,是一种分而治之的设计理念。通过多线程或者多进程多机器的模式,可以将小任务处理分发给更多的CPU处理,降低单个CPU的计算量,通过并发/并行提高任务的完成速度,提高系统的性能。

具体细节如上图,Master对任务进行切分,并放入任务队列;然后,触发Worker处理任务。实际操作中,任务的分配有多种形式,如Master主动拉起Workder进程池或线程池,并将任务分配给Worker;或者由Worker主动领取任务,这样的Worker一般是常驻进程;还有一种解耦的方式,即Master指做任务的接收、切分和结果统计,指定Worker的数量和性能指标,但不参与Worker的实际管理,而是交由第三方调度监控和调度Worker。
代码实现Master-Worker模式:
Master代码:
package com.hjf.master_worker; import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue; /**
* Master
* @author huangjianfei
*/
public class Master
{
//1:应该有一个承载任务的集合
private ConcurrentLinkedQueue<Task> workQueue = new ConcurrentLinkedQueue<Task>(); //2:使用hashmap去承载所有的worker对象 ThreadName------Worker
private HashMap<String,Thread> workers = new HashMap<>(); //3:使用一个容器承载每一个worker并行执行任务的结果集
private ConcurrentHashMap<String,Object> resultMap = new ConcurrentHashMap<String, Object>(); //4:构造方法
public Master(Worker worker,int workerCount){
//在worker中添加两个引用 workQueue用于任务的领取 resultMap用于任务的提交
worker.setWorkerQueue(this.workQueue);
worker.setResultMap(this.resultMap); for (int i = 0; i < workerCount; i++)
{
workers.put("子节点 "+i, new Thread(worker));
}
} //5:提交方法
public void submit(Task task){
workQueue.add(task);
} //6:需要有一个执行的方法(启动应用程序 让所有的worker工作)
public void execute(){
//遍历workers 分别去执行每一个worker
for (Map.Entry<String,Thread> me: workers.entrySet())
{
me.getValue().start();
}
} /**
* 判断所有的worker是否执行完毕
*/
public boolean isCompleted()
{
//遍历所有的worker 只要有一个没有停止 那么就代表没有结束
for (Map.Entry<String,Thread> me: workers.entrySet())
{
if(me.getValue().getState() != Thread.State.TERMINATED){
return false;
}
}
return true;
} /**
* 计算最终的结果集
* @return
*/
public int getResult(){
int result = 0;
for (Map.Entry<String,Object> me : resultMap.entrySet())
{
result += (Integer)me.getValue();
}
return result;
}
}
Worker代码实现:
package com.hjf.master_worker; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue; /**
* Worker
* @author huangjianfei
*/
public class Worker implements Runnable
{
private ConcurrentLinkedQueue<Task> workQueue; private ConcurrentHashMap<String, Object> resultMap; public void setWorkerQueue(ConcurrentLinkedQueue<Task> workQueue)
{
this.workQueue = workQueue;
} public void setResultMap(ConcurrentHashMap<String, Object> resultMap)
{
this.resultMap = resultMap;
} @Override
public void run()
{
//处理一个个任务
while(true){
//从队列中取出一个元素
Task input = this.workQueue.poll();
if(null == input) break;
//真正的去做业务处理
Object outPut = handle(input);
//存放任务的结果
this.resultMap.put(String.valueOf(input.getId()), outPut);
}
} //单独抽出来 给子类重写,更加灵活
public Object handle(Task input){
return null;
} /**
* 处理业务 应该抽象出来 子类去具体实现业务逻辑
* @param input
*/
// private Object handle(Task input)
// {
// Object outPut = null;
// if(null == input) return null;
// try
// {
// //表示处理task任务的耗时,可能是数据的加工,也可能是操作数据库
// Thread.sleep(5000);
// //模拟真实的业务场景
// outPut = input.getPrice();
// } catch (InterruptedException e)
// {
// e.printStackTrace();
// }
// return outPut;
// } }
Task代码实现:
package com.hjf.master_worker;
/**
* 任务
* @author huangjianfei
*/
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;
} }
Worker子类,在以后的开发中可以按照自己的需求去设计相关的Worker的子类:
package com.hjf.master_worker; public class MyWorker1 extends Worker
{
@Override
public Object handle(Task input)
{
Object outPut = null;
if(null == input) return null;
try
{
//表示处理task任务的耗时,可能是数据的加工,也可能是操作数据库
Thread.sleep(5000);
//模拟真实的业务场景
outPut = input.getPrice();
} catch (InterruptedException e)
{
e.printStackTrace();
}
return outPut;
}
}
Main测试类代码:
package com.hjf.master_worker; import java.util.Random;
/**
* 主线程测试类
* @author huangjianfei
*/
public class Main
{
public static void main(String[] args)
{
System.out.println("我的机器可用的Processor数量:"+Runtime.getRuntime().availableProcessors());
// 使用worker子类实现具体的业务,更加灵活
Master master = new Master(new MyWorker1(), Runtime.getRuntime().availableProcessors());
Random r = new Random();
//提交100个任务
for (int i = 0; i <= 100; i++)
{
Task t = new Task();
t.setId(i);
t.setName("任务 "+i);
t.setPrice(r.nextInt(1000));
master.submit(t);
} //执行所有的worker
master.execute(); long start = System.currentTimeMillis();//记录时间 while(true){
//全部的worker执行结束的时候去计算最后的结果
if(master.isCompleted()){
long end = System.currentTimeMillis() - start;//计算耗时
//计算结果集
int result = master.getResult();
System.out.println("执行最终结果: "+result + " 执行耗时 "+end);
break;
}
} } }
Master-Worker设计模式介绍的更多相关文章
- java23种设计模式—— 一、设计模式介绍
Java23种设计模式全解析 目录 java23种设计模式-- 一.设计模式介绍 java23种设计模式-- 二.单例模式 java23种设计模式--三.工厂模式 java23种设计模式--四.原型模 ...
- 一文看懂Java Worker 设计模式
Worker模式 想解决的问题 异步执行一些任务,有返回或无返回结果 使用动机 有些时候想执行一些异步任务,如异步网络通信.daemon任务,但又不想去管理这任务的生命周.这个时候可以使用Worker ...
- JavaBean中DAO设计模式介绍(转)
一.信息系统的开发架构 客户层-------显示层-------业务层---------数据层---------数据库 1.客户层:客户层就是客户端,简单的来说就是浏览器. 2.显示层:JSP/Ser ...
- JavaBean中DAO设计模式介绍
一.信息系统的开发架构 客户层-------显示层-------业务层---------数据层---------数据库 1.客户层:客户层就是client,简单的来说就是浏览器. 2.显示层:JSP/ ...
- 「PHP」设计模式介绍
引言 最近再看PHP设计模式相关的一些技术文章,网上有关PHP的设计模式范例很少,这里做一些总结仅供参考,不足之处望提出. 参考资料: <大话设计模式>程杰 什么是设计模式 设 ...
- 设计模式——介绍与工厂模式(扁平管理模式VS职业经理人模式)
本文主要对设计模式进行大概解说.特别是对工厂模式进行简明的解析: 一.设计模式的分类 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式. ...
- c#设计模式介绍
序号 模式名称 模式描述 应用场景 例子 1 单例模式 (SigletonPattern) 保证一个类仅有一个实例,并提供一个访问它的全局访问点. • 单例类只能有一个实例. • 单例类必须自己创建自 ...
- Python:设计模式介绍--单例模式
单例模式 1.单例是只有一个实例2.通过静态字段+静态字段伪造出一个单例效果3.什么时候用:当所有实例中封装的数据相同时,创建单例模式(eg:连接池) 用单例模式创建连接池: class CP: __ ...
- Repository 设计模式介绍
在DDD设计中大家都会使用Repository pattern来获取domain model所需要的数据. 1.什么是Repository? "A Repository mediates b ...
随机推荐
- html5 p1练习1,移动页面,标准标签布局
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...
- Python数据分析Numpy库方法简介(三)
补充: np.ceil()向上取整 3.1向上取整是4 np.floor()向下取整 数组名.resize((m,n)) 重置行列 基础操作 np.random.randn()符合正态分布(钟行/高斯 ...
- Vue基础进阶 之 自定义指令
自定义指令-----钩子函数 自定义指令 除了内置指令,Vue也允许用户自定义指令: 注册指令:通过全局API Vue.directive可以注册自定义指令: 自定义指令的钩子函数: bind: in ...
- Splay详解
平衡树实际很简单的 以下讲解都以Luogu P3369 [模板]普通平衡树为例 我不会带指针的Splay,所以我就写非指针型的Splay Splay是基于二叉查找树(bst)实现的 什么是二叉查找树呢 ...
- 【题解】Luogu P2763 试题库问题
原题传送门 这题很简单啊 从源点向k类题目分别连流量为所需数量的边 从每道题向汇点连一条流量为1的边(每题只能用1次) 从类型向对应的题目连一条流量为1的边 跑一遍最大流 如果最大流小于所需题目数量, ...
- Python爬虫(四)——豆瓣数据模型训练与检测
前文参考: Python爬虫(一)——豆瓣下图书信息 Python爬虫(二)——豆瓣图书决策树构建 Python爬虫(三)——对豆瓣图书各模块评论数与评分图形化分析 数据的构建 在这张表中我们可以发现 ...
- D2欧拉路,拓扑排序,和差分约束
第一题:太鼓达人:BZOJ3033 题意:给出k,求一个最长的M位01串,使其从每一个位置向后走k个得到 的M个k位01串互不相同(最后一个和第一个相邻,即是一个环).输出 字典序最小的答案. 2 ≤ ...
- sql server 查询某个表被哪些存储过程调用
sql server 查询某个表被哪些存储过程调用 select distinct object_name(id) from syscomments where id in (select id fr ...
- i.MX6UL -- PWM用户空间使用方法【转】
本文转载自:https://blog.csdn.net/u014486599/article/details/53010114 i.MX6UL -- PWM用户空间使用方法 开发平台: 珠海鼎芯D51 ...
- JAVA基础知识笔记
1.类只能用Public修饰,不能使用protected.private修饰.也可以不加修饰符,称做友好类. 2.类的实体元素包含成员变量和方法的定义,成员变量分为实例变量和类变量(static修饰的 ...