一、Master-Worker设计模式

Master-Worker模式是常用的并行设计模式。它的核心思想是,系统有两个进程协议工作:Master进程和Worker进程。Master进程负责接收和分配任务,Worker进程负责处理子任务。当各个Worker进程将子任务处理完后,将结果返回给Master进程,由Master进行归纳和汇总,从而得到系统结果。

Master-Worker模式的好处是,它能将大任务分解成若干个小任务,并发执行,从而提高系统性能。而对于系统请求者Client来说,任务一旦提交,Master进程就会立刻分配任务并立即返回,并不会等系统处理完全部任务再返回,其处理过程是异步的。

二、Master-Worker设计模式代码实现

1、创建Task任务对象

 package com.ietree.basicskill.mutilthread.designpattern.masterworker;

 /**
* Created by Root on 5/12/2017.
*/
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;
}
}

2、实现Worker对象

 package com.ietree.basicskill.mutilthread.designpattern.masterworker;

 import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue; /**
* Created by Root on 5/12/2017.
*/
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 (input == null) {
break;
}
// 真正的去做业务处理
//Object output = handle(input);
// 改造
Object output = MyWorker.handle(input);
// 返回处理结果集
this.resultMap.put(Integer.toString(input.getId()), output);
}
} // private Object handle(Task input) {
// Object output = null;
// try {
// // 表示处理task任务的耗时,可能是数据的加工,也可能是操作数据库......
// Thread.sleep(500);
// output = input.getPrice();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// return output;
// } // 优化,考虑让继承类去自己实现具体的业务处理
public static Object handle(Task input) {
return null;
} }

3、为了使程序更灵活,将具体的业务执行逻辑抽离,在具体的Worker对象去实现,如这里的MyWorker对象

 package com.ietree.basicskill.mutilthread.designpattern.masterworker;

 /**
* Created by Root on 5/13/2017.
*/
public class MyWorker extends Worker { public static Object handle(Task input) {
Object output = null;
try {
// 表示处理task任务的耗时,可能是数据的加工,也可能是操作数据库......
Thread.sleep(500);
output = input.getPrice();
} catch (InterruptedException e) {
e.printStackTrace();
}
return output;
} }

4、Master类

 package com.ietree.basicskill.mutilthread.designpattern.masterworker;

 import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue; /**
* Created by Root on 5/12/2017.
*/
public class Master { // 1、使用一个ConcurrentLinkedQueue集合来装载所有需要执行的任务
private ConcurrentLinkedQueue<Task> workQueue = new ConcurrentLinkedQueue<Task>(); // 2、使用HashMap来装载所有的worker对象
private HashMap<String, Thread> workers = new HashMap<String, Thread>(); // 3、使用一个容器承装每一个worker并发执行任务的结果集
private ConcurrentHashMap<String, Object> resultMap = new ConcurrentHashMap<String, Object>(); // 4、构造方法
public Master(Worker worker, int workerCount) {
// 每一个worker对象都需要有Master的引用,workQueue用于任务的领取,resultMap用于任务的提交
worker.setWorkerQueue(this.workQueue);
worker.setResultMap(this.resultMap); for (int i = 0; i < workerCount; i++) {
workers.put("子节点" + Integer.toString(i), new Thread(worker));
}
} // 5、提交方法
public void submit(Task task) {
this.workQueue.add(task);
} // 6、需要有一个执行的方法(启动应用程序,让所有的worker工作)
public void execute() {
for (Map.Entry<String, Thread> me : workers.entrySet()) {
me.getValue().start();
}
} // 7、判断线程是否执行完毕
public boolean isComplete() {
for (Map.Entry<String, Thread> me : workers.entrySet()) {
// 判断所有的线程状态是否属于已停止状态
if (me.getValue().getState() != Thread.State.TERMINATED) {
return false;
}
}
return true;
} // 8、返回结果集数据
public int getResult() {
int ret = 0;
for (Map.Entry<String, Object> me : resultMap.entrySet()) {
// 汇总逻辑
ret += (Integer) me.getValue();
}
return ret;
} }

5、测试,具体调用实现

 package com.ietree.basicskill.mutilthread.designpattern.masterworker;

 import java.util.Random;

 /**
* Created by Root on 5/13/2017.
*/
public class MasterWorkerTest { public static void main(String[] args) { // Master master = new Master(new Worker(), 10);
// 改造
// Master master = new Master(new MyWorker(), 10);
// 改造(获取当前机器可用线程数)
System.out.println("我的机器可用Processors数量:" + Runtime.getRuntime().availableProcessors());
Master master = new Master(new MyWorker(), Runtime.getRuntime().availableProcessors()); Random r = new Random();
for (int i = 1; i <= 10; i++) {
Task t = new Task();
t.setId(i);
t.setName("任务" + i);
t.setPrice(r.nextInt(1000));
master.submit(t);
}
master.execute(); long start = System.currentTimeMillis(); while (true) {
if (master.isComplete()) {
long end = System.currentTimeMillis() - start;
int ret = master.getResult();
System.out.println("最终的结果:" + ret + ",执行耗时:" + end);
break;
}
}
} }

程序输出:

我的机器可用Processors数量:20
最终的结果:4473,执行耗时:500

从上面的运行结果来看,程序最终执行时间几乎就等于一个线程单独运行的时间,在此注意的是,同时执行的线程数是根据你执行此程序的机器配置决定的。

并发模型之Master-Worker设计模式的更多相关文章

  1. 一网打尽 Java 并发模型

    本篇文章我们来探讨一下并发设计模型. 可以使用不同的并发模型来实现并发系统,并发模型说的是系统中的线程如何协作完成并发任务.不同的并发模型以不同的方式拆分任务,线程可以以不同的方式进行通信和协作. 并 ...

  2. nginx并发模型与traffic_server并发模型简单比较

    ginx并发模型: nginx 的进程模型采用的是prefork方式,预先分配的worker子进程数量由配置文件指定,默认为1,不超过1024.master主进程创建监听套接口,fork子进程以后,由 ...

  3. memcached源码剖析4:并发模型

    memcached是一个典型的单进程系统.虽然是单进程,但是memcached内部通过多线程实现了master-worker模型,这也是服务端最常见的一种并发模型.实际上,除了master线程和wor ...

  4. Java进阶7 并发优化2 并行程序设计模式

    Java进阶7 并发优化2 并行程序设计模式20131114 1.Master-worker模式 前面讲解了Future模式,并且使用了简单的FutureTask来实现并发中的Future模式.下面介 ...

  5. 课堂笔记--Strom并发模型

    Strom并发模型:     topology是如何运行的?(可与mapreduce对比)         第一层:cluster         第二层:supervisor(host.node.机 ...

  6. 构建自己的Java并发模型框架

    Java的多线程特性为构建高性能的应用提供了极大的方便,可是也带来了不少的麻烦.线程间同步.数据一致性等烦琐的问题须要细心的考虑,一不小心就会出现一些微妙的,难以调试的错误. 另外.应用逻辑和线程逻辑 ...

  7. 构建Java并发模型框架

    Java的多线程特性为构建高性能的应用提供了极大的方便,但是也带来了不少的麻烦.线程间同步.数据一致性等烦琐的问题需要细心的考虑,一不小心就会出现一些微妙的,难以调试的错误.另外,应用逻辑和线程逻辑纠 ...

  8. Java并发模型框架

    构建Java并发模型框架 Java的多线程特性为构建高性能的应用提供了极大的方便,但是也带来了不少的麻烦.线程间同步.数据一致性等烦琐的问题需要细心的考虑,一不小心就会出现一些微妙的,难以调试的错误. ...

  9. 并发模型与IO模型梳理

    并发模型 常见的并发模型一般包括3类,基于线程与锁的内存共享模型,actor模型和CSP模型,其中尤以线程与锁的共享内存模型最为常见.由于go语言的兴起,CSP模型也越来越受关注.基于锁的共享内存模型 ...

随机推荐

  1. 0基础浅谈反射型xss(2)

    0x1:回顾前文疑惑“先闭合,在构造” 上一篇,我们说到了xss的一个触发精髓,“先闭合,在构造”,对于前面的先闭合,我们来简单的解释一下:   首先说,为什么要闭合? 因为HTML标签都是成对出现的 ...

  2. solr安装教程

    Solr Solr is the popular, blazing-fast, open source enterprise search platform built on Apache Lucen ...

  3. vue封装插件并发布到npm上

    vue封装插件并发布到npm上 项目初始化 首先,要创建项目,封装vue的插件用webpack-simple很合适,vue init webpack-simple 项目名称此命令创建我们的项目的目录, ...

  4. Maven 问题笔记汇总

    Web项目通过Maven部署到Tomcat的错误. Maven环境下面多项目之间的引用 Maven 远程仓库下载慢的的解决方案 Intellij IDEA 像eclipse那样给maven添加依赖 I ...

  5. 【JS新手教程】浏览器弹出div层1

    JS中,可以弹出一个层来进行提示等作用,方法是利用css样式display样式,当display等于none时,该元素就不会在页面显示出来,而且元素也不会占空间.就是用户触发某些事件时,动态修改该样式 ...

  6. 查看 page页面某一个属性在 web ui 中的位置。

    1:例如查询 description 属性在web ui 中的位置. 2:进入订单编辑状态,鼠标放到该字段上,按F2 3:出现该字段的详细信息,包括:component,contextNode 4: ...

  7. CentOS7.6下模拟iSCSI,Windows来连

    如题,在CentOS7上模拟一个iSCSI设备,然后在Windows Server 2008上连接这个iSCSI设备 第一步,CentOS7上的操作.CentOS7上安装iSCSI模拟器需要3个包,我 ...

  8. springcloud(四)-Eureka Server集群

    Eureka Server的高可用 这一节我们接着上一节说. 有分布式应用开发经验的朋友应该发现,前文编写的单节点Eureka Server并不适合线上生产环境.Eureka Client会定时连接E ...

  9. Visual Studio 跨平台開發實戰(2) - Xamarin.iOS 基本控制項介紹 (转帖)

    前言 在上一篇文章中, 我們介紹了Xamarin 以及簡單的HelloWorld範例, 這次我們針對iOS的專案目錄架構以及基本控制項進行說明. 包含UIButton,, UISlider, UISw ...

  10. Html5与本地App资料整理分析

    最近开发了一个小的手机网站,重新了解了本地应用,html5,混合应用,webApp等概念,整理下相关的资料,略带自己的思考 用户固有的使用习惯 在<2012年度 HTML5状况及发展形势报告.p ...