并行模式之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的简单应 ...
随机推荐
- CodeForces - 1214D D. Treasure Island
题目链接:https://vjudge.net/problem/2728294/origin 思路:可以抽象成管道,先试试能不能找到一个通道能通到终点, 如果可以则封锁这个通道,一个石头即可, 再试试 ...
- 百万年薪python之路 -- 异常处理
异常处理 1.错误的分类: 1.语法错误:(这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正) #语法错误示范一 if #语法错误示范二 def test: pass #语法错 ...
- PowerBI开发 第十五篇:Power BI的行级安全
Power BI支持行级安全(Row-Level Security,RLS)的权限控制,用于限制用户对Dashboard.报表和DataSet的访问.用户浏览的报表是相同的,但是看到的数据却是不同的. ...
- kubernetes实战(二十七):CentOS 8 二进制 高可用 安装 k8s 1.16.x
1. 基本说明 本文章将演示CentOS 8二进制方式安装高可用k8s 1.16.x,相对于其他版本,二进制安装方式并无太大区别.CentOS 8相对于CentOS 7操作更加方便,比如一些服务的关闭 ...
- Excel在线预览(通过poi转html,含里面的图片)
支持03和07excel转html,直接上代码 测试类 /** * 主方法 * @author asus * */ public class App2 { public static void mai ...
- Connection activation failed Device not managed by NetworkManager
1)查看NetworkManager服务是否启动 ps aux |grep NetworkManager 使用service NetworkManager start 命令启动该网络管理程序 2) 一 ...
- zabbix导入数据库报错1046 (3D000) : No database selected
Zabbix导入数据库时报错 使用如下命令导入Zabbix数据库时报错 zcat /usr/share/doc/zabbix-server-mysql/create.sql.gz | mysql -u ...
- 对比讲解lambda表达式与传统接口函数实现方式
在本号之前写过的一些文章中,笔者使用了lambda表达式语法,一些读者反映说代码看不懂.本以为java 13都已经出了,java 8中最重要特性lambda表达式大家应该都掌握了,实际上还是存在大量的 ...
- CAT客户端如何从Apollo中读取配置?
运行环境 以下就是这个示例的运行环境,如果版本号不一样,区别也应该不会很大,可以根据实际情况做相应调整. JDK 8 spring boot 2.0.7.RELEASE cat-client 3.0. ...
- CSPS模拟 74
T1 贪心,如果用set考虑一下multi. T2 难道是我的疑问都太过sb? 从来没人愿意认真思考一下我的问题. 更好,思考量这东西本该我自己来补. 设$dp[i][j]$为i个点的森林,j个点在特 ...