架构师养成记--10.master-worker模式
master-worker模式是一种并行计算模式,分为master进程和worker进程两个部分,master是担任总管角色,worker才是执行具体任务的地方。
总体流程应该是这样的:

具体一点,代码实现流程应该是这样的:

client:
import java.util.Random;
public class Main {
public static void main(String[] args) {
Master master = new Master(new Worker(), 20);//并发数20,也就是有20个Worker在工作
Random r = new Random();
for(int i = 1; i <= 100; i++){//总共有100个任务
Task t = new Task();
t.setId(i);
t.setPrice(r.nextInt(1000));
master.submit(t);//提交任务,向WorkerQueue<Task> 中加入元素
}
master.execute();//启动所有的worker
long start = System.currentTimeMillis();
while(true){
if(master.isComplete()){//100个任务执行完成
long end = System.currentTimeMillis() - start;
int priceResult = master.getResult();//获取所有任务的执行结果
System.out.println("最终结果:" + priceResult + ", 执行时间:" + end);
break;
}
}
}
}
Master:
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue; public class Master { //1 有一个盛放任务的容器
private ConcurrentLinkedQueue<Task> workQueue = new ConcurrentLinkedQueue<Task>(); //2 需要有一个盛放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.setWorkQueue(this.workQueue);
worker.setResultMap(this.resultMap); for(int i = 0; i < workerCount; i ++){
this.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 priceResult = 0;
for(Map.Entry<String, Object> me : resultMap.entrySet()){
priceResult += (Integer)me.getValue();
}
return priceResult;
}
Worker:
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue; public class Worker implements Runnable { private ConcurrentLinkedQueue<Task> workQueue;
private ConcurrentHashMap<String, Object> resultMap; public void setWorkQueue(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);
this.resultMap.put(Integer.toString(input.getId()), output);
}
} private Object handle(Task input) {
Object output = null;
try {
//处理任务的耗时。。 比如说进行操作数据库。。。
Thread.sleep(500);
output = input.getPrice();
} catch (InterruptedException e) {
e.printStackTrace();
}
return output;
} }
Task:
public class Task {
private int id;
private int price ;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
架构师养成记--10.master-worker模式的更多相关文章
- 架构师养成记--9.future模式讲解
什么是future模式呢?解释这个概念之前我们先来了解一个场景吧,财务系统的结账功能,这个功能可能是每个月用一次,在这一个月中相关的数据量已经积累得非常大,这一个功能需要调用好几个存储过程来完成.假如 ...
- 架构师养成记--35.redis集群搭建
前记:redis哨兵经验之谈.哨兵做主从切换可能要花费一两秒,这一两秒可能会丢失很多数据.解决方法之一是在java代码中做控制,try catch 到 链接断开的异常就sleep 一两秒钟再conti ...
- 架构师养成记--11.Executor概述
常用方法 Executors.newFiexdPool(int nThreads);固定线程数量的线程池: Executors.newSingleThreadExecutor();单个线程的线程池: ...
- 架构师养成记--8.Queue
一.ConcurrentLinkedQueue 是一个适合在高并发场景下,无锁,无界的,先进先出原则.不允许为null值,add().offer()加入元素,这两个方法没区别:pull().peek( ...
- 架构师养成记--15.Disruptor并发框架
一.概述 disruptor对于处理并发任务很擅长,曾有人测过,一个线程里1s内可以处理六百万个订单,性能相当感人. 这个框架的结构大概是:数据生产端 --> 缓存 --> 消费端 缓存中 ...
- 架构师养成记--6.单例和多线程、ThreadLocal
一.ThreadLocal 使用wait/notify方式实现的线程安全,性能将受到很大影响.解决方案是用空间换时间,不用锁也能实现线程安全. 来看一个小例子,在线程内的set.get就是thread ...
- 架构师养成记--4.volatile关键字
volatile修饰的变量可在多个线程间可见. 如下代码,在子线程运行期间主线程修改属性值并不对子线程产生影响,原因是子线程有自己独立的内存空间,其中有主内存中的变量副本. public class ...
- 架构师养成记--3.synchronized细节问题
一.synchronized有锁重入的特点,某个线程得到对象的锁后,再次请求此对象可以再次得到改对象的锁.如下示例,在method1中调用method2,在method2中调用method3,而met ...
- 架构师养成记--34.Redis持久化
---恢复内容开始--- redis是一个支持持久化的内存数据库,也就是搜redis需要经常将内存中的数据同步到硬盘来保证持久化.redis持久化有两种方式. snapshotting(快照)默认方式 ...
随机推荐
- MyEclipse相关部署问题
部署Tomcat如果用MyEclipse自动部署方式很有可能出现一个问题: 服务器关联的这个项目却关联到其他的项目上,导致运行时还在运行以前的项目 解决方法: 将状态提示栏的service里的tomc ...
- Android View的滑动 动画
[scrollTo/scrollBy] //控件内的文字会移动,但是控件本身不会移动,而且移动到控件之外之后,文字也就看不见了 if(v.equals(button2)){ button2.scrol ...
- mac下查看.mobileprovision文件及钥匙串中证书.cer文件
mac下查看.mobileprovision文件及钥匙串中证书.cer文件 一. mobileprovision文件查看 xxx.mobileprovision是ios开发中的设备描述文件,里面有证书 ...
- 手机游戏渠道SDK接入工具项目分享(一)缘起
#剧情章节 # 上周刚结束一个外包的项目,开发手机游戏渠道SDK聚合接入工具的,现在有空回顾整理一下这个项目开发过程,因涉嫌商业秘密不会提供项目代码,只谈下开发思路和掉过的坑. 本人多年从事手机互联网 ...
- linux 环境下运行STS时 出现must be available in order to run STS
linux 环境下运行ECLIPSE时 出现 “ A Java Runtime Environment (JRE) or Java Development Kit (JDK) must be avai ...
- iOS项目相关@AFN&SDWeb的二次封装
一,AFNetworking跟SDWebImge是功能强大且常用的第三方,然而在实际应用中需要封装用来复用今天就跟大家分享一下AFN&SDWeb的二次封装 1. HttpClient.h及.m ...
- javascript中需要自行定义的函数
1.toString()与String() 使用方式:x.toString();-----String(x); String是万能的方法,而x.toString()则有局限性,无法将undefined ...
- apache-shiro入门<一>
Apache Shiro是一个强大而灵活的开源安全框架(本来想传到网盘供大家下载,但是鉴于国内网盘动不动就要关闭清楚用户数据:所以我提供了另一个shiro的中文文档下载链接:http://downlo ...
- 简历生成平台项目开发-STEP4第二次项目例会讨论
时间:2016.7.15周五7点半 地点:图书馆 讨论主题:交流各自手头项目进展,确定下一步任务 内容:按照之前的讨论的任务大家各自汇报进度. 汇报人:谭卓.尹忠诚 内容:1.基于富文本编辑器的模板, ...
- mac 下JDK 与 tomcat 的安装与配置
一.Mac下JDK的安装 1.先检测Mac是否已经安装过JDK,在终端中输入java 或者 javac 显示说明,表明已经安装过JDK,JDK版本查询终端键入java -version,终端会返回JD ...