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设计模式介绍的更多相关文章

  1. java23种设计模式—— 一、设计模式介绍

    Java23种设计模式全解析 目录 java23种设计模式-- 一.设计模式介绍 java23种设计模式-- 二.单例模式 java23种设计模式--三.工厂模式 java23种设计模式--四.原型模 ...

  2. 一文看懂Java Worker 设计模式

    Worker模式 想解决的问题 异步执行一些任务,有返回或无返回结果 使用动机 有些时候想执行一些异步任务,如异步网络通信.daemon任务,但又不想去管理这任务的生命周.这个时候可以使用Worker ...

  3. JavaBean中DAO设计模式介绍(转)

    一.信息系统的开发架构 客户层-------显示层-------业务层---------数据层---------数据库 1.客户层:客户层就是客户端,简单的来说就是浏览器. 2.显示层:JSP/Ser ...

  4. JavaBean中DAO设计模式介绍

    一.信息系统的开发架构 客户层-------显示层-------业务层---------数据层---------数据库 1.客户层:客户层就是client,简单的来说就是浏览器. 2.显示层:JSP/ ...

  5. 「PHP」设计模式介绍

    引言   最近再看PHP设计模式相关的一些技术文章,网上有关PHP的设计模式范例很少,这里做一些总结仅供参考,不足之处望提出. 参考资料: <大话设计模式>程杰   什么是设计模式   设 ...

  6. 设计模式——介绍与工厂模式(扁平管理模式VS职业经理人模式)

    本文主要对设计模式进行大概解说.特别是对工厂模式进行简明的解析: 一.设计模式的分类 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式. ...

  7. c#设计模式介绍

    序号 模式名称 模式描述 应用场景 例子 1 单例模式 (SigletonPattern) 保证一个类仅有一个实例,并提供一个访问它的全局访问点. • 单例类只能有一个实例. • 单例类必须自己创建自 ...

  8. Python:设计模式介绍--单例模式

    单例模式 1.单例是只有一个实例2.通过静态字段+静态字段伪造出一个单例效果3.什么时候用:当所有实例中封装的数据相同时,创建单例模式(eg:连接池) 用单例模式创建连接池: class CP: __ ...

  9. Repository 设计模式介绍

    在DDD设计中大家都会使用Repository pattern来获取domain model所需要的数据. 1.什么是Repository? "A Repository mediates b ...

随机推荐

  1. 21 python的魔法方法(转)

    魔法方法 含义   基本的魔法方法 __new__(cls[, ...]) 1. __new__ 是在一个对象实例化的时候所调用的第一个方法2. 它的第一个参数是这个类,其他的参数是用来直接传递给 _ ...

  2. python 减少可调用对象的参数个数

    有一个被其他python 代码使用的callable 对象,可能是一个回调函数或者是一个处理器,但是它的参数太多了,导致调用时出错 如果需要减少某个函数的参数个数, 你可以使用functools.pa ...

  3. 史上最全的PHP常用函数大全,不看看你就out了(还会不断更新哦!)

    纪录了PHP的一些常用函数和函数代码!不要错过了哦. PHP的一些常用函数usleep() 函数延迟代码执行若干微秒.unpack() 函数从二进制字符串对数据进行解包.uniqid() 函数基于以微 ...

  4. zabbix 乱码问题

    一.乱码原因 查看cpu负载,中文乱码如下 这个问题是由于zabbix的web端没有中文字库,我们最需要把中文字库加上即可 二.解决zabbix乱码方法 2.1 上传字体文件到zabbix中 找到本地 ...

  5. jquery简易tab切换

    切换tab 使用eq()函数 eq() 方法将匹配元素集缩减值指定 index 上的一个. //为项目 3 设置红色背景 <ul> <li>list item 1</li ...

  6. 关于mysql触发器和存储过程的理解

    内容源自:一篇很棒的 MySQL 触发器学习教程 一.触发器概念 触发器(trigger):监视某种情况,并触发某种操作,它是提供给程序员和数据分析员来保证数据完整性的一种方法,它是与表事件相关的特殊 ...

  7. poj1985和poj1849(树的直径)

    题目传送门:poj1985 树是连通无环图,树上任意两点之间的路径是唯一的.定义树上任 意两点u, v的距离为u到v路径上边权的和.树的直径MN为树上最长路 径,即点M和N是树上距离最远的两个点. 题 ...

  8. 在新获取git中项目时出现的问题汇总

    新下拉git项目,今天遇到的问题,因为刚配置实用jdk和idea,所以有可能在打开springboot项目时查看mysql数据库驱动显示为红色. 之后看到pom文件也没有错,最后发现才是在项目中还没有 ...

  9. .Net中json序列化与反序列化

    NuGet中下载Newtonsoft.Json插件. public class JsonHelper<T>{ public static string ModelToJsonString( ...

  10. 扩展的GM命令

    命令 说明 例子 .rl all 重载核心所有自定义数据表   .rl item 重载item_template   .backup a 备份Auth数据库   .backup c 备份Charact ...