并行模式之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的简单应 ...
随机推荐
- 后缀数组(SA)
学习了LRJ神犇的代码.orz. 首先真心建议了解下基数排序!!且要有一定的c++程序经验,否则程序很难看懂. 然后对着下面的程序调试(假装你已经会了算法思想) 弄个一个礼拜一下午就能学会了. 该算法 ...
- HTTP协议详解(二)—— HTTP响应
HTTP响应(Response) 响应与请求一样分成三个部分:响应行.响应头.响应体. 1.响应行: 格式 - HTTP/1.1 200 OK 2.响应头: 部分头属性解释 - Location:这个 ...
- SpringBoot系列教程之Bean加载顺序之错误使用姿势辟谣
在网上查询 Bean 的加载顺序时,看到了大量的文章中使用@Order注解的方式来控制 bean 的加载顺序,不知道写这些的博文的同学自己有没有实际的验证过,本文希望通过指出这些错误的使用姿势,让观文 ...
- H5 video踩坑实录
前段时间公司APP做了一个APP论坛会议,嵌入了h5播放器.我以为很简单,没想到,这正是我踩进泥潭的开始... (想要吸取经验的小伙伴可以慢慢往下看,想要解决方案的直接看最后!) 一.一开始我以为直接 ...
- 一文理解java对象初始化顺序
例子 Talk is cheap, Show you the code! public class ParentClass { static int parentStaticField = 1; ...
- abp中将SqlServer切换为MySQL
一.移除默认SQL Server相关包 在EntityFrameworkCore项目下移除包Microsoft.EntityFrameworkCore.SqlServer.Microsoft.Enti ...
- HTTP 304状态码的详细讲解
首先,对于304状态码不应该认为是一种错误,而是对客户端有缓存情况下服务端的一种响应. 客户端在请求一个文件的时候,发现自己缓存的文件有 Last Modified ,那么在请求中会包含 If Mod ...
- Pandas 时间序列
# 导入相关库 import numpy as np import pandas as pd 在做金融领域方面的分析时,经常会对时间进行一系列的处理.Pandas 内部自带了很多关于时间序列相关的工具 ...
- 我把数表A了
真kx 之前打一棵沙雕主席树,复杂度和正解一毛一样,结果常数爆炸了! 我一直天真的认为卡卡常这题就能AC,然后卡常卡到死也没A掉,极限数据大概跑了1.1s 今天终于打正解了,离线处理,可以用常数更小的 ...
- java架构之路-(NoSql专题)MongoDB快速上手
NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL".在现代的计算系统上每天网络上都会产生庞大的数据量.这些数据有很大一部分是由关系数据库管理系统(RD ...