并行模式之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的简单应 ...
随机推荐
- Kafka源码研究--Comsumer获取partition下标
背景 由于项目上Flink在设置parallel多于1的情况下,job没法正确地获取watermark,所以周末来研究一下一部分,大概已经锁定了原因: 虽然我们的topic只设置了1的partitio ...
- vue 代码迁移的坑
由于开发需要,开发过程中总会遇到由于代码调试.svn/git上传等过程中,总会出现代码迁移文件的需求,很多时候,迁移过后总会出现一些大大小小的问题, 首先,需要迁移文件内有没有系统自动隐藏的文件(例如 ...
- PHPStorm 10 配置PHPUnit
PHPStorm 10 配置PHPUnit PHPUnit的安装 自己用的是Xampp,PHPUnit好像自带不好用. 不说废话: 自己看 According to official site htt ...
- Unity事件系统
# 1.前言Unity中事件/委托有着广泛的应用,本文通过封装一个简易的事件的系统,来统一管理消息的传递.此功能在简易应用或者事件较少的体现不出太好的作用,但是对于事件应用较多时,可以减少脚本之间的耦 ...
- fenby C语言
P1框架 1#include <stdio.h> 2 3int main(){ 4 printf(“C语言我来了”); 5 return 0; 6} P2main()门 P3计 ...
- ubuntu18.04 flink-1.9.0 Standalone集群搭建
集群规划 Master JobManager Standby JobManager Task Manager Zookeeper flink01 √ √ flink02 √ √ flink03 √ √ ...
- 痞子衡嵌入式:飞思卡尔i.MX RTyyyy系列MCU硬件那些事(2.2)- 在串行NOR Flash XIP调试原理
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔i.MX RTyyyy系列EVK在串行NOR Flash调试的原理. 本文是i.MXRT硬件那些事系列第二篇的续集,在第二篇首集 ...
- jwt token
1 ,session 认证机制: ,用户登录,传递用户名和密码给客户端 ,服务器进行用户名和密码的校验,如果校验成功,将用户保存到session ,将sessionid通过cookie返回给客服端,客 ...
- Vue---mock.js 使用
mockjs 概述 在我们的生产实际中,后端的接口往往是较晚才会出来,并且还要写接口文档,于是我们的前端的许多开发都要等到接口给我们才能进行,这样对于我们前端来说显得十分的被动,于是有没有可以制造假数 ...
- vue2.0 与 vue3.0 配置的区别
提示:要了解vue2.0与vue3.0区别,首先你要熟悉vue2.0 从最明显最简单的开始 项目目录结构 可以明显的看出来,vue2.0与3.0在目录结构方面,有明显的不同(vue3.0我是安装了cs ...