这样的模型是最经常使用的并行模式之中的一个,在Nginx源代码中有涉及到有想看的能够去这个大神的博客了解一下http://blog.csdn.net/marcky/article/details/6014733,这位大神写的有些简洁。

从思想的角度来说。它主要由两类进程进行协作:各自是Master进程和Worker进程。Master进程负责接受和分配任务,Worker进程负责处理子任务,当Worker将子任务处理完毕后。将结果返回给Master进程。由Master进程做归纳和汇总。得到终于结果。详细流程能够看此图

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdmVadW5TaGFv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

这样的模式可以将一个大任务分解成若干个小任务去运行,适合一些耗时比較久的任务,可以提高系统的吞吐量。

一个相对完整的模型应该具备下面功能

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdmVadW5TaGFv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

在借鉴了java性能优化书上的列子。上面实现了一个简单的Master-Worker模式

  1. package com.thread;
  2.  
  3. import java.util.HashMap;
  4. import java.util.Iterator;
  5. import java.util.Map;
  6. import java.util.Queue;
  7. import java.util.Set;
  8. import java.util.concurrent.ConcurrentHashMap;
  9. import java.util.concurrent.ConcurrentLinkedDeque;
  10.  
  11. public class Master_Worker {
  12. public static void main(String args[])
  13. {
  14. long start = System.currentTimeMillis();
  15. Master_Worker master_Worker = new Master_Worker(new PlusWorker(), 11);
  16. for (int i = 0; i < 100; i++) {
  17. master_Worker.submit(i);
  18. }
  19. master_Worker.execute();
  20. int re = 0;
  21. Map<String, Object> result_Map = master_Worker.getResultMap();
  22. while (result_Map.size()>0||!master_Worker.isComplete()) {
  23. Set<String> keysSet = result_Map.keySet();
  24. String keyString = null;
  25. for (String string : keysSet) {
  26. keyString = string;
  27. break;
  28. }
  29. Integer i = null;
  30. if (keyString !=null) {
  31. i = (Integer) result_Map.get(keyString);
  32. }
  33. if (i!=null) {
  34. re+=i;
  35. }
  36. if (keyString!=null) {
  37. result_Map.remove(keyString);
  38. }
  39. }
  40. long end = System.currentTimeMillis();
  41. System.out.println("结果:"+re+"-运行之间"+(end-start));
  42. int sum = 0;
  43. start = System.currentTimeMillis();
  44. for (int i = 1; i <= 100; i++) {
  45. sum+=i*i*i;
  46. try {
  47. Thread.sleep(100);
  48. } catch (InterruptedException e) {
  49. // TODO Auto-generated catch block
  50. e.printStackTrace();
  51. }
  52. }
  53. end = System.currentTimeMillis();
  54. System.out.println("结果:"+sum+"-运行之间"+(end-start));
  55. }
  56. // 任务队列
  57. protected Queue<Object> workerQueue = new ConcurrentLinkedDeque<>();
  58. // Worker进程队列
  59. protected Map<String, Thread> threadMap = new HashMap<>();
  60. // 子任务处理结果集
  61. protected Map<String, Object> resultMap = new ConcurrentHashMap<>();
  62.  
  63. // 是否全部的子任务都结束了
  64. public boolean isComplete() {
  65. for (Map.Entry<String, Thread> entry : threadMap.entrySet()) {
  66. if (entry.getValue().getState() != Thread.State.TERMINATED) {
  67. return false;
  68. }
  69. }
  70. return true;
  71. }
  72.  
  73. // Master的构造,须要一个Worker进程逻辑,和须要的Worker进程数量
  74. public Master_Worker(Worker woker, int countWorker) {
  75. woker.setWorkQueue(workerQueue);
  76. woker.setResultMap(resultMap);
  77. for (int i = 0; i < countWorker; i++) {
  78. threadMap.put(Integer.toString(i),
  79. new Thread(woker, Integer.toString(i)));
  80. }
  81.  
  82. }
  83.  
  84. //返回子任务结果集
  85. public Map<String, Object> getResultMap()
  86. {
  87. return resultMap;
  88. }
  89. //提交任务
  90. public void submit(Object job) {
  91. workerQueue.add(job);
  92. }
  93. public void execute()
  94. {
  95. for (Map.Entry<String, Thread> entry : threadMap.entrySet()) {
  96. if (entry.getValue().getState() != Thread.State.TERMINATED) {
  97. entry.getValue().start();
  98. }
  99. }
  100. }
  101. }
  102.  
  103. class Worker implements Runnable {
  104.  
  105. // 任务队列,用于取得子任务
  106. protected Queue<Object> workQueue;
  107. // 子任务处理结果集
  108. protected Map<String, Object> resultMap;
  109.  
  110. public void setWorkQueue(Queue<Object> workQueue) {
  111. this.workQueue = workQueue;
  112. }
  113.  
  114. public void setResultMap(Map<String, Object> resultMap) {
  115. this.resultMap = resultMap;
  116. }
  117.  
  118. // 子任务处理逻辑,在子类中实现详细逻辑
  119. public Object handle(Object input) {
  120. /* 这里能够写自己想要做的事情 */
  121. return input;
  122. }
  123.  
  124. @Override
  125. public void run() {
  126. // TODO Auto-generated method stub
  127. while (true) {
  128. // 获取子任务
  129. Object inputObject = workQueue.poll();
  130. if (inputObject == null) {
  131. break;
  132. }
  133. // 处理子任务
  134. Object reObject = handle(inputObject);
  135. resultMap.put(Integer.toString(inputObject.hashCode()), reObject);
  136. }
  137. }
  138. }
  139.  
  140. /*
  141. * 扩展自己的类
  142. * */
  143. class PlusWorker extends Worker{
  144. @Override
  145. public Object handle(Object input) {
  146. // TODO Auto-generated method stub
  147. //在这里能够自己实现自己的业务逻辑等,在这里我让线程睡眠了100毫秒,模拟任务运行
  148.  
  149. try {
  150. Thread.sleep(100);
  151. } catch (InterruptedException e) {
  152. // TODO Auto-generated catch block
  153. e.printStackTrace();
  154. }
  155. Integer i = (Integer) input;
  156. return i*i*i;
  157. }
  158. }

这里的大多数都是借鉴java性能优化一书,加上自己的改编和简单介绍。

java线程模型Master-Worker的更多相关文章

  1. eventloop & actor模式 & Java线程模型演进 & Netty线程模型 总结

    eventloop的基本概念可以参考:http://www.ruanyifeng.com/blog/2013/10/event_loop.html Eventloop指的是独立于主线程的一条线程,专门 ...

  2. 1、java线程模型

    要了解多线程,先需要把java线程模型搞清楚,否则有时候很难理清楚一个问题. 硬件多线程: 物理机硬件的并发问题跟jvm中的情况有不少相似之处,物理机的并发处理方案对于虚拟机也有相当大的参考意义.在买 ...

  3. JS线程模型&Web Worker

    js线程模型 客户端javascript是单线程,浏览器无法同时运行两个事件处理程序 设计为单线程的理论是,客户端的javascript函数必须不能运行太长时间,否则会导致web浏览器无法对用户输入做 ...

  4. Java线程模型

    并发不一定要依赖多线程(如PHP中很常见的多进程并发),但是在Java里面谈论并发,大多数都与线程脱不开关系. 线程是比进程更轻量级的调度执行单位,线程的引入,可以把一个进程的资源分配和执行调度分开, ...

  5. java线程基础知识----java线程模型

    转载自http://www.cnblogs.com/nexiyi/p/java_memory_model_and_thread.html 1. 概述 多任务和高并发是衡量一台计算机处理器的能力重要指标 ...

  6. java并发笔记之java线程模型

    警告⚠️:本文耗时很长,先做好心理准备 java当中的线程和操作系统的线程是什么关系? 猜想: java thread —-对应-—> OS thread Linux关于操作系统的线程控制源码: ...

  7. 七. 多线程编程2.Java线程模型

    Java运行系统在很多方面依赖于线程,所有的类库设计都考虑到多线程.实际上,Java使用线程来使整个环境异步.这有利于通过防止CPU循环的浪费来减少无效部分. 为更好的理解多线程环境的优势可以将它与它 ...

  8. 理解微信小程序的双线程模型

    有过微信小程序开发经验的朋友应该都知道"双线程模型"这个概念,本文简单梳理一下双线程模型的一些科普知识,学识浅薄,若有错误欢迎指正. 我以前就职于「小程序·云开发」团队,在对外的一 ...

  9. 【转载】 Java线程面试题 Top 50

    Java线程面试题 Top 50 不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题.Java语言一个重要的特点就是内置了对并发的支持,让Java大受企业和程序员 的欢迎.大多数待遇丰厚的J ...

随机推荐

  1. 检查点--JMeter也有之二“检查点”

    检查点:简单的来理解一下,上一章讲到,我们对用户名和密码进行了参数化,那么怎样来判断jmeter有没有正确调用test.dat里面的文件呢.当然,我们可以从结果图表中查看.但我还是想在“登录”这个地方 ...

  2. Request.Url.Port 获取不到正确的端口号

    今天遇到一个很奇怪的事情,用request.url.port来获取一个请求的端口,返回是80 ,很纳闷啊我的请求上面是http://www.XX.com:8088 啊,怎么会是80啊,太不可思议了! ...

  3. The Art of Mocking

    One of the challenges developers face when writing unit tests is how to handle external dependencies ...

  4. ios frame,bound和center

    frame:指的是视图在父视图的坐标系统中的大小和位置. bound:指的是视图在试图本身的坐标系统中的大小(位置起点是原点). center:指的是视图在父视图坐标系统中的中心点. 贴张苹果官网的图 ...

  5. 常用VBA小技巧

    用对话框选取文件路径(单个文件) 删除导入csv等文本文件后留下的 Data connections 增加新的工作表并并命名 Worksheets.Add(After:=Worksheets(Work ...

  6. JAVA常见算法题(十八)

    package com.xiaowu.demo; /** * 两个乒乓球队进行比赛,各出三人.甲队为a,b,c三人,乙队为x,y,z三人,以抽签决定比赛名单. 有人向队员打听比赛的名单:a说他不和x比 ...

  7. ES6中关于数据类型的拓展:Symbol类型

    ES5中包含5种原始类型:字符串.数值.布尔值.null.undefined.ES6引入了第6种原始类型——Symbol. ES5的对象属性名都是字符串,很容易造成属性名冲突.比如,使用了一个他人提供 ...

  8. 一个基于RSA算法的Java数字签名例子

    原文地址:一个基于RSA算法的Java数字签名例子 一.前言: 网络数据安全包括数据的本身的安全性.数据的完整性(防止篡改).数据来源的不可否认性等要素.对数据采用加密算法加密可以保证数据本身的安全性 ...

  9. 机器学习第3课:线性代数回顾(Linear Algebra Review)

    3.1  矩阵和向量 如图:这个是 4×2 矩阵,即 4 行 2 列,如 m 为行,n 为列,那么 m×n 即 4×2 矩阵的维数即行数×列数 矩阵元素(矩阵项): Aij 指第 i 行,第 j 列的 ...

  10. Linux查看目录大小

    du -ah --max-depth=1 a表示显示目录下所有的文件和文件夹(不含子目录) h表示以人类能看懂的方式 max-depth表示目录的深度