Master-Worker 模式是常用的并行计算模式。它的核心思想是系统由两类进程协同工作,Master和Worker进程。Master负责接收和分配任务,Worker负责处理子任务。当各个Worker子进程处理完毕后,会将结果返回给Master,由Master做归纳和小结。其好处是能够将一个大任务分解成若干个小任务,并行执行,从而提高系统的吞吐量。

Master-Worker模式结构图

代码架构:

Master 负责接收和分配任务
Worker 负责处理子任务
Main 主函数,启动类

Master类

public class Master {

	//1 有一个盛放任务的容器  1.任务不需要阻塞   2.性能高   3.线程安全,每一个worker来这里拿100个task,所以要考虑线程安全。
private ConcurrentLinkedQueue<Task> workQueue = new ConcurrentLinkedQueue<Task>(); //2 需要有一个盛放worker的集合 1.不存在多线程争抢场景
private HashMap<String, Thread> workers = new HashMap<String, Thread>(); //3 需要有一个盛放每一个worker执行任务的结果集合 结果集,多个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;
} }

需要说明的几点:

1.存放任务的容器,需要一个高并发,线程安全,性能好的容器,因为每一个Worker都回来这里取任务执行,存在线程安全问题,因此选择ConcurrentLinkedQueue。

2.存放结果的容器,同样,worker也持有他的引用,每一个worker做完事情后,会把结果写入这个map中,存在线程安全问题,所以采用ConcurrentHashMap。

3.存放worker的容器没有线程并发访问,只在worker中进行了遍历,不存在线程安全问题。

Worker类

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);
System.out.println("当前线程"+Thread.currentThread().getName()+" 计算完毕"+ 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;
} }

Worker类需要实现Runnable接口

任务类

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;
}
@Override
public String toString() {
return "Task [id=" + id + ", price=" + price + "]";
} }

任务类比较简单,不再敖述。

接下来是启动类

public class Main {

	public static void main(String[] args) {
/**20个worker*/
Master master = new Master(new Worker(), 20); Random r = new Random();
//100 个任务
for(int i = 1; i <= 1000; i++){
Task t = new Task();
t.setId(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 priceResult = master.getResult();
System.out.println("最终结果:" + priceResult + ", 执行时间:" + end);
break;
}
} }
}

运行结果如下

总结

Master-Worker模式是一种将串行任务并行化的方案,被分解的子任务在系统中可以被并行处理,同时,如果有需要,Master进程不需要等待所有子任务都完成计算,就可以根据已有的部分结果集计算最终结果集。

Java并发案例05---Master-Worker模式的更多相关文章

  1. Java并发编程(05):悲观锁和乐观锁机制

    本文源码:GitHub·点这里 || GitEE·点这里 一.资源和加锁 1.场景描述 多线程并发访问同一个资源问题,假如线程A获取变量之后修改变量值,线程C在此时也获取变量值并且修改,两个线程同时并 ...

  2. Java描述设计模式(05):原型模式

    本文源码:GitHub·点这里 || GitEE·点这里 一.原型模式简介 1.基础概念 原型模式属于对象的创建模式.通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出 ...

  3. java设计模式案例详解:工厂模式

    1.简单工厂模式 在不考虑扩展的情况下还是很好用的,其实我们写代码也很经常用到,其主要理解在于传入不同参数则构建不同对象,只有一个工厂,如需添加产品涉及到扩展需要修改比较多的东西,不符合开闭原则,如下 ...

  4. java:并发编程-Callable与Future模式

    自己对线程池的理解: coresize 3 maxsize 5 blockLinkedQuenue 3 当提交的任务在<=3时,创建三个线程干活 大于3时,把任务先加入阻塞式队列,当有空闲的核心 ...

  5. java设计模式案例详解:代理模式

    代理模式就是用一个第三者的身份去完成工作,其实际意义跟字面意思其实是一样的,理解方式有很多,还是例子直观. 本例的实现类是实现买票功能,实际应用想要添加身份验证功能,利用代理模式添加验证步骤.上例子: ...

  6. Java并发案例04---生产者消费者问题03--使用ReentrantLock

    /** * 面试题:写一个固定容量同步容器,拥有put和get方法,以及getCount方法, * 能够支持2个生产者线程以及10个消费者线程的阻塞调用 * * 使用wait和notify/notif ...

  7. Java并发案例02---生产者消费者问题

    package example; import java.util.LinkedList; import java.util.concurrent.TimeUnit; public class MyC ...

  8. Java并发案例01---多线程之死锁

    多线程之死锁案例一 package example; /** * 模拟死锁 * @author maple * */ public class DeadLock { public int flag = ...

  9. Java并发基础05. 传统线程同步通信技术

    先看一个问题: 有两个线程,子线程先执行10次,然后主线程执行5次,然后再切换到子线程执行10,再主线程执行5次--如此往返执行50次. 看完这个问题,很明显要用到线程间的通信了, 先分析一下思路:首 ...

随机推荐

  1. 十一:image 图片

    属性名 类型 默认值 说明 src String   图片资源地址 mode String 'scaleToFill' 图片裁剪.缩放的模式 binderror HandleEvent   当错误发生 ...

  2. Spring.Net---2、IoC/DI基本概念

    ---------------------------------------------------------------------------------- (1)IoC/DI的概念 IoC ...

  3. ASP.NET之HTML

    1.什么是html 用来描述网页的2.开发工具我们肯定是用vs啦3.img src 图片地址 <img src="img/aa.bmp" />; 4.超链接a标签 hr ...

  4. [javaSE] GUI(练习-列出指定目录内容)

    获取Frame对象 获取TextField对象 获取TextArea对象 获取Button对象 调用Frame对象的add()方法,添加进去 调用TextField对象的getText()方法,可以获 ...

  5. Quartz大致介绍(一)

    1. 介绍 Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,是完全由java开发的一个开源的任务日程管理系统,“任务进度管理器”就是一个在预先确定(被纳 ...

  6. jdk锁相关

    锁类型 可重入锁:在执行对象中所有同步方法不用再次获得锁 可中断锁:在等待获取锁过程中可中断 公平锁: 按等待获取锁的线程的等待时间进行获取,等待时间长的具有优先获取锁权利 读写锁:对资源读取和写入的 ...

  7. PowerDesigner16导出SQL时如何添加注释

    添加注释方法 https://jingyan.baidu.com/article/47a29f24652e44c0142399c3.html 重点是修改value的值 alter table [%QU ...

  8. KaTeX.js

    KaTeX.js 官网:https://khan.github.io/KaTeX/

  9. 使用ArcGIS Chef Cookbook轻松搞掂WebGIS平台部署

    1.安装Chef Client v12版本. 2.复制arcgis cookbook资源到Chef安装目录. 3.考虑到一般部署的服务器环境无法连接互联网,所以需要事先部署ArcGIS Cookboo ...

  10. Maximum Product Subarray 最大连续乘积子集

    Find the contiguous subarray within an array (containing at least one number) which has the largest ...