一、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. Maven的Mirror和Repository 的详细讲解

    1 Repository(仓库) 1.1 Maven仓库主要有2种: remote repository:相当于公共的仓库,大家都能访问到,一般可以用URL的形式访问 local repository ...

  2. nginx的几种负载均衡策略

    转自https://www.cnblogs.com/1214804270hacker/p/9325150.html 一.关于Nginx的负载均衡 在服务器集群中,Nginx起到一个代理服务器的角色(即 ...

  3. C语言数据结构之哈夫曼树及哈夫曼编码的实现

    代码清单如下: #pragma once #include<stdio.h> #include"stdlib.h" #include <string.h> ...

  4. Java多线程——volatile关键字、发布和逸出

    1.volatile关键字 Java语言提供了一种稍弱的同步机制,即volatile变量.被volatile关键字修饰的变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在每次读取volatit ...

  5. 了解到的Web攻击技术

    (1)XSS(Cross-Site Scripting,跨站脚本攻击): 指通过存在安全漏洞的Web网站注册用户的浏览器内运行非法的HTML标签或者JavaScript进行的一种攻击. (2)SQL注 ...

  6. ThreadLocal系列(三)-TransmittableThreadLocal的使用及原理解析

    ThreadLocal系列(三)-TransmittableThreadLocal的使用及原理解析 上一篇:ThreadLocal系列(二)-InheritableThreadLocal的使用及原理解 ...

  7. HDU4641 || 6194多校 (后缀自动机-最少出现K次的字串个数 || 恰好出现K次字符串的个数)

    http://acm.hdu.edu.cn/showproblem.php?pid=4641 http://acm.hdu.edu.cn/showproblem.php?pid=6194 题意: 开始 ...

  8. CentOS 7下安装RabbitMQ

    下载erlang:http://www.erlang.org/downloads ,otp_src_20.3.tar.gz 下载RabbitMQ: http://www.rabbitmq.com ,r ...

  9. php实现函数可变参数列表

    使用func_get_args().func_num_args().func_get_arg() 可以构造一个可变参数列表的函数. 首先大致介绍以上三个函数. (1)array func_get_ar ...

  10. hr中间插入字体

    修饰CSS:hr:before { content: "??";} hr:after { content: " This is an <hr> element ...