并行模式之Master-Worker模式
并行模式之Master-Worker模式
一)、Master-Worker模式
作用: 将一个大任务分解成若干个小任务,分发给多个子线程执行。
注: 将大任务分解成小任务,小任务的实现逻辑要相同。
二)、Master-Worker模式的结构
Master-Worker的核心思想:由Master进程和Worker进程实现。
1)、Master进程:
接收和分配任务,整合最终的处理结果。
内部结构组成:
1.Worker进程队列
作用:执行Master分配的任务,开启多线程处理数据。
2.子任务队列
作用:接收任务。
3.子结果集
作用:整合多个线程的最终处理结果。
注:Master进程分配任务后会立即返回,不会等待系统全部处理完返回,处理过
程是异步的,client不会出现等待状态。
2)、Worker进程
实现Runable接口,定义一个handle()方法,在方法里实现小任务的业务逻辑,在run()方法中调用handle()方法
内部结构组成:
1.子任务队列
作用:接收Master分配的任务。
2.结果集队列
作用:将处理的结果返给Master
3.handle()方法
作用:定义小任务的业务逻辑。
注:所有的Wroker对象共享Master的Worker队列,和结果集.
三)、Master-Worker的代码实现
使用Master-Worker模式实现 :
计算 1~100的立方和( 1^3 + 2^3 + ... + 100^3 )
思路:将计算任务分解为100个小任务,每个子任务计算单独的立方和,最后将计
算结果返回给master。
Master类:
/**
* Master类:
* 内部维护了一个Worker进程队列、任务队列、结果集
*/
public class Master {
/**
* 任务队列, ConcurrentLinkedDeque: 基于链表的并发队列
*/
protected Queue workerQueue = new ConcurrentLinkedDeque();
/**
* Worker进程队列
*/
Map<String, Thread> threadMap = new HashMap<>();
/**
* 结果集
*/
Map<String, Object> resultMap = new HashMap<>();
/**
* Master的构造,需要一个进程对象和进程数量
*/
public Master(Worker worker, int countWorker){
//将master的workerQueue和resultMap和Worker关联
worker.setWorkerQueue(workerQueue);
worker.setResultMap(resultMap);
//根据需要的进程数量,创建进程
for(int i = 0; i < countWorker; i++){
//Integer.toString(i)为线程的名字
threadMap.put(Integer.toString(i), new Thread(worker,Integer.toString(i)));
}
}
/**
* master进程提交任务
*/
public void submit(Object input){
workerQueue.add(input);
}
/**
* master分配任务,执行任务,开启多线程
*/
public void execute(){
for(Map.Entry<String,Thread> entry : threadMap.entrySet()){
entry.getValue().start();
}
}
/**
* 判断是否所有的子任务都结束了
*/
public boolean isComplete(){
//判断worker进程的状态是否都等于终止状态
for(Map.Entry<String,Thread> entry : threadMap.entrySet()){
if(entry.getValue().getState() != Thread.State.TERMINATED){
return false;
}
}
return true;
}
public Queue getWorkerQueue() {
return workerQueue;
}
public void setWorkerQueue(Queue workerQueue) {
this.workerQueue = workerQueue;
}
public Map<String, Thread> getThreadMap() {
return threadMap;
}
public void setThreadMap(Map<String, Thread> threadMap) {
this.threadMap = threadMap;
}
public Map<String, Object> getResultMap() {
return resultMap;
}
public void setResultMap(Map<String, Object> resultMap) {
this.resultMap = resultMap;
}
}
Worker类:实现Runable接口,定义handle()方法,在run()中调用handle()
/**
* Worker类:
* 小任务的逻辑实现类
*/
public class Worker implements Runnable{
/**
* 接收master的workerQueue,用于开启线程处理多个小任务
*/
protected Queue workerQueue;
/**
* 接收master的resultMap,将各个小任务的处理结果返回给Master
*/
protected Map<String, Object> resultMap;
/**
* 小线程的具体逻辑,接收任务并处理任务
* 参数: input,分解的小任务
*/
public Object handle(Object input){
return input;
}
/**
* 从任务列表中获取任务,调用handle()方法,执行任务
*/
@Override
public void run() {
while(true){
//获取任务列表的任务
Object input = workerQueue.poll();
//判断任务列表是否还有任务,若没有,则终止线程。
if(input == null){
break;
}
//有任务,调用handle()方法,执行任务
Object result = handle(input);
//将结果放在master的resultMap中
resultMap.put(Integer.toString(input.hashCode()),result);
}
}
public Queue getWorkerQueue() {
return workerQueue;
}
public void setWorkerQueue(Queue workerQueue) {
this.workerQueue = workerQueue;
}
public Map<String, Object> getResultMap() {
return resultMap;
}
public void setResultMap(Map<String, Object> resultMap) {
this.resultMap = resultMap;
}
}
PlushWorker类:继承了Worker类,重写handle()方法,定义任务的处理逻辑
**
* 继承Worker类,定义handle()的业务逻辑
*/
public class PlushWorker extends Worker{
/**
* 对任务进行处理,在run()方法中调用该方法
* @param input
* @return
*/
@Override
public Object handle(Object input){
int i = (Integer)input;
return i * i * i;
}
}
main类:使用master计算 1~100的立方和( 1^3 + 2^3 + ... + 100^3 )
/**
* 使用Master-Worker模式实现 :
* 计算 1~100的立方和( 1^3 + 2^3 + ... + 100^3 )
* 1.将计算任务分解为100个小任务,每个子任务计算单独的立方和,最后将计算结果返回给master
*/
public class CubicAndCalculate {
public static void main(String[] args) {
//创建Master对象,开启五个线程对任务进行处理
Master master = new Master(new PlushWorker(), 5);
//将大任务分解成100个小任务
for(int i = 1; i <= 100; i++){
master.submit(i);
}
//开启多线程,并发的处理多个小任务
master.execute();
//master可以不用等全部的任务执行完便可以获取任务的执行结果
Map<String, Object> resultMap = master.getResultMap();
Integer re = 0;
//加入两个判断是因为,每取出一个resultMap中的数据,都要对该数据删除,若消费resultMap的速度比生成的快,可通过判断任务线程是否执行完毕来控制数据的获取
while(resultMap.size() > 0 || !master.isComplete()){
//获取map的所有键
Set<String> set = resultMap.keySet();
String key = null;
for(String k : set){
key = k;
break;
}
Integer i = null;
//判断map中是否有数据,若key值为null,就不进行获取值操作
if(key != null){
i = (Integer) resultMap.get(key);
}
//如果key存在,i !=null,则对返回的部分的任务的立方和进行累加,并移除resultMap中对应的项
if(i != null){
re += i;
resultMap.remove(key);
}
}
System.out.println(re);
}
}
结果:
25502500
并行模式之Master-Worker模式的更多相关文章
- Master和worker模式
让和hadoop的设计思想是一样的,Master负责分配任务和获取任务的结果,worker是真正处理业务逻辑的. 使用ConcurrentLikedQueue去承载所有的任务,因为会有多个worker ...
- Apache常用2种工作模式prefork和worker比较
Apache两种常用工作模式:prefork和worker. prefork MPM prefork是一个非线程型的.预派生的MPM,使用多个进程,每个进程在某个确定的时间只单独处理一个连接,效率高, ...
- Apache的prefork模式和worker模式(转)
prefork模式这个多路处理模块(MPM)实现了一个非线程型的.预派生的web服务器,它的工作方式类似于Apache 1.3.它适合于没有线程安全库,需要避免线程兼容性问题的系统.它是要求将每个请求 ...
- Apache的prefork模式和worker模式
prefork模式这个多路处理模块(MPM)实现了一个非线程型的.预派生的web服务器,它的工作方式类似于Apache 1.3.它适合于没有线程安全库,需要避免线程兼容性问题的系统.它是要求将每个请求 ...
- puppet(5)-master/agent模式
master/agent模式的工作流程 agent每隔固定时长会向master端发送nodename(自己的节点名,节点名至关重要)和 facts ,并且向服务器端请求自己的catalog. mast ...
- [PHP] apache在worker模式配置fastcgi使用php-fpm
1.准备: dpkg -L apache2查看所有安装的apache2的应用 a2query -M查看apache2使用的模式 httpd -l旧版本查看当前apache模式 2.查看apache的进 ...
- apache常用的两种工作模式 prefork和worker
apache作为现今web服务器用的最广泛也是最稳定的开源服务器软件,其工作模式有许多中,目前主要有两种模式:prefork模式和worker模式 一.两种模式 prefork模式: prefork是 ...
- jenkins的Master/Slave模式
一. Master/Slave模式 分担jenkins服务器的压力,任务分配到其它执行机来执行 Master:Jenkins服务器 Slave:执行机(奴隶机).执行Master分配的任务,并返回任务 ...
- Ubuntu下配置Apache的Worker模式
其实Apache本身的并发能力是足够强大的,但是Ubuntu默认安装的是Prefork模式下的Apache.所以导致很多人后面盲目的去 安装lighttpd或者nginx一类替代软件.但是这类软件有一 ...
- Puppet基于Master/Agent模式实现LNMP平台部署
前言 随着IT行业的迅猛发展,传统的运维方式靠大量人力比较吃力,运维人员面对日益增长的服务器和运维工作,不得不把很多重复的.繁琐的工作利用自动化处理.前期我们介绍了运维自动化工具ansible的简单应 ...
随机推荐
- static self 区别与总结
<?php /** * static self 区别与总结 * 总结: * 1.在 PHP 里,在没有继承时候,你用self::class 和 static::class是一样的,都是获取当前类 ...
- odoo联调补充
odoo联调补充(剑飞花 373500710) 安装某些py插件包时需要vc++2008发行包,可访问下面地址. 安装python-ldap一定要用支持9.44postgresSQL的exe安装,同样 ...
- Unity - HasExitTime用法
本文详细分析了AnimatorController中动画切换过渡问题,即Translation过渡及hasExitTime的问题.方法为对实际项目中的所有情况进行分类,规划逻辑图,可视化分析解决这些问 ...
- textView 实现完成收键盘操作
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSStr ...
- Visual Studio Code 添加C/C++编译功能
VS Code作为一个文本/代码编辑器,相较于VS比较轻量化,而且可以支持C/C++.Python等多种语言,并具有丰富的拓展模块. 但是作为一个编辑器,在VS Code上安装C/C++模块之后,并不 ...
- 分享一次大厂的技术面试通过,却因学历被拒发 offer 的悲惨经历
概述 今天心情很down,快周末了,说点不开心的事情给大家开心一下,上周面试心仪已久的大厂,技术面很顺利的通过一面/二面/三面,最后到HR面也很顺利,然后被问到学历(自考本科)后,HR 语气发生一些转 ...
- ES6对象简洁语法
对象(object)是 JavaScript 最重要的数据结构.ES6 对它进行了重大升级,本章介绍数据结构本身的改变及语法应用细节. 1.属性的简洁表示法 ◆ ES6 允许直接写入变量和函数,作为对 ...
- Linux学习使用Vim
Vim是从 vi 发展出来的一个文本编辑器.vi编辑器是所有Unix及Linux系统下标准的编辑器,他就相当于windows系统中的记事本一样.代码补完.编译及错误跳转等方便编程的功能特别丰富,在程序 ...
- 使用msfvenom生成木马
msfvenom Options: -p, --payload < payload> 指定需要使用的payload(攻击荷载).如果需要使用自定义的payload,请使用& #03 ...
- Python3获取豆瓣图书标签的前20本热门书籍(一)
介绍 第一篇主要获取豆瓣的大分类.大分类下的具体分类以及具体分类下的前20本热门书籍,第二篇对获取的数据进行分析. 准备 Python3.6.requests.BeautifulSoup4 演示 代码 ...