Java多线程Master-Worker模式
Java多线程Master-Worker模式,多适用于需要大量重复工作的场景中。
例如:使用Master-Worker计算0到100所有数字的立方的和
1.Master接收到100个任务,每个任务需要0到100中每个数字的立方,这里为了效果,每个任务再sleep一秒,
Master需要将这些任务放到一个支持高并发的非阻塞队列queue中如:ConcurrentLinkedQueue<E>。
2.Master创建10个worker去执行这100个任务,并准备一个支持高并发且线程安全的hashMap作为结果集的容器如:ConcurrentHashMap。
3.每个worker需要循环的从queue中获取任务然后执行,执行完毕后把结果放到hashMap中,直到queue为空,所有任务执行完毕后退出。
4.Master循环判断结果集hashMap中是否有已经执行完毕的结果,如果有就使用,使用完毕就立即移除该结果,直到所有的线程都退出。
5.所有任务执行完毕,Master也处理完所有任务的结果,程序结束
Master不需要等待所有的任务执行完毕就可以处理已完成的任务结果,Master和worker可以同时进行工作,这样节省了大量等待worker执行结束的时间
Master源码
- package masterWorker;
- import java.lang.Thread.State;
- import java.util.Collection;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.Map.Entry;
- import java.util.Queue;
- import java.util.Set;
- import java.util.concurrent.ConcurrentHashMap;
- import java.util.concurrent.ConcurrentLinkedQueue;
- import org.junit.Test;
- public class Master {
- public static void main(String[] args) {
- long befor = System.currentTimeMillis();
- //任务队列
- Queue<Integer> taskQueue = new ConcurrentLinkedQueue<>();
- //工人map
- Map<String,Thread> workers = new HashMap<>();
- //结果集
- Map<String,Long> resultMap = new ConcurrentHashMap<>();
- //最终结果
- long result = 0;
- //提交100个任务
- for (int i = 0; i < 100; i++) {
- taskQueue.add(i);
- }
- //添加10个工人
- for (int i = 0; i < 10; i++) {
- workers.put(i+"", new Thread(new Worker(taskQueue,resultMap),"工人"+i));
- }
- //启动所有工人线程
- Collection<Thread> threads = workers.values();
- for (Thread thread : threads) {
- thread.start();
- }
- while(resultMap.size() > 0 || !isComplete(workers)){
- Set<String> keySet = resultMap.keySet();
- //每次从resultMap中取一个结果出来进行使用
- String key = null;
- for (String string : keySet) {
- if(string != null){
- key = string;
- break;
- }
- }
- Long value = null;
- if(key != null){
- value = resultMap.get(key);
- }
- //能取到结果就使用,没有结果继续循环
- if(value != null){
- //获取到一个运算结果就使用
- result = result+value;
- //使用后从结果集中移除
- resultMap.remove(key);
- }
- }
- long after = System.currentTimeMillis();
- System.out.println("结果耗时:"+(after - befor));
- System.out.println(result);
- }
- /**
- * 判断所有的工人是否已经完成工作
- * @param workers
- * @return
- */
- private static boolean isComplete(Map<String,Thread> workers){
- for (Entry<String, Thread> entry : workers.entrySet()) {
- if(entry.getValue().getState() != State.TERMINATED){
- return false;
- }
- }
- return true;
- }
- @Test
- public void test() throws InterruptedException{
- long befor = System.currentTimeMillis();
- long result = 0;
- for (int i = 0; i < 100; i++) {
- long cube = i*i*i;
- result = result+cube;
- Thread.sleep(100);
- }
- long after = System.currentTimeMillis();
- System.out.println("结果耗时:"+(after - befor));
- System.out.println(result);
- }
- }
Worker源码
- package masterWorker;
- import java.util.Map;
- import java.util.Queue;
- public class Worker implements Runnable{
- private Queue<Integer> queue;
- private Map<String,Long> resultMap;
- public Worker(Queue<Integer> queue,Map<String,Long> resultMap) {
- this.queue = queue;
- this.resultMap = resultMap;
- }
- @Override
- public void run() {
- //不断循环从队列中取出任务进行运算,直到队列为空
- while(true){
- if(queue.peek() != null){
- String name = Thread.currentThread().getName();
- int poll =(int) queue.poll();
- long result = poll*poll*poll;
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- resultMap.put(poll+"", result);
- System.out.println(name+"完成"+poll+"的运算,结果为:"+result);
- }else{
- break;
- }
- }
- }
- }
经典的Master-Worker源码实例
- package masterWorker.classics;
- import java.util.Map;
- import java.util.Set;
- public class Main {
- /**
- * @param args
- */
- public static void main(String[] args) {
- //固定使用5个Worker,并指定Worker
- Master m = new Master(new PlusWorker(), Runtime.getRuntime().availableProcessors());
- //提交100个子任务
- for(int i=0;i<100;i++){
- m.submit(i);
- }
- //开始计算
- m.execute();
- int re= 0;
- //保存最终结算结果
- Map<String ,Object> resultMap =m.getResultMap();
- //不需要等待所有Worker都执行完成,即可开始计算最终结果
- while(resultMap.size()>0 || !m.isComplete()){
- Set<String> keys = resultMap.keySet();
- String key =null;
- for(String k:keys){
- key=k;
- break;
- }
- Integer i =null;
- if(key!=null){
- i=(Integer)resultMap.get(key);
- }
- if(i!=null){
- //最终结果
- re+=i;
- }
- if(key!=null){
- //移除已经被计算过的项
- resultMap.remove(key);
- }
- }
- System.out.println(re);
- }
- }
- package masterWorker.classics;
- import java.util.Map;
- import java.util.Queue;
- public class Worker implements Runnable{
- //任务队列,用于取得子任务
- protected Queue<Object> workQueue;
- //子任务处理结果集
- protected Map<String ,Object> resultMap;
- public void setWorkQueue(Queue<Object> workQueue){
- this.workQueue= workQueue;
- }
- public void setResultMap(Map<String ,Object> resultMap){
- this.resultMap=resultMap;
- }
- //子任务处理的逻辑,在子类中实现具体逻辑
- public Object handle(Object input){
- return input;
- }
- @Override
- public void run() {
- while(true){
- //获取子任务
- Object input= workQueue.poll();
- if(input==null){
- break;
- }
- //处理子任务
- Object re = handle(input);
- resultMap.put(Integer.toString(input.hashCode()), re);
- }
- }
- }
- package masterWorker.classics;
- public class PlusWorker extends Worker {
- @Override
- public Object handle(Object input) {
- Integer i =(Integer)input;
- return i*i*i;
- }
- }
- package masterWorker.classics;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.Queue;
- import java.util.concurrent.ConcurrentHashMap;
- import java.util.concurrent.ConcurrentLinkedQueue;
- public class Master {
- // 任务队列
- protected Queue<Object> workQueue = new ConcurrentLinkedQueue<Object>();
- // Worker进程队列
- protected Map<String, Thread> threadMap = new HashMap<String, Thread>();
- // 子任务处理结果集
- protected Map<String, Object> resultMap = new ConcurrentHashMap<String, Object>();
- // 是否所有的子任务都结束了
- public boolean isComplete() {
- for (Map.Entry<String, Thread> entry : threadMap.entrySet()) {
- if (entry.getValue().getState() != Thread.State.TERMINATED) {
- return false;
- }
- }
- return true;
- }
- // Master的构造,需要一个Worker进程逻辑,和需要Worker进程数量
- public Master(Worker worker, int countWorker) {
- worker.setWorkQueue(workQueue);
- worker.setResultMap(resultMap);
- for (int i = 0; i < countWorker; i++) {
- threadMap.put(Integer.toString(i),
- new Thread(worker, Integer.toString(i)));
- }
- }
- // 提交一个任务
- public void submit(Object job) {
- workQueue.add(job);
- }
- // 返回子任务结果集
- public Map<String, Object> getResultMap() {
- return resultMap;
- }
- // 开始运行所有的Worker进程,进行处理
- public void execute() {
- for (Map.Entry<String, Thread> entry : threadMap.entrySet()) {
- entry.getValue().start();
- }
- }
- }
Java多线程Master-Worker模式的更多相关文章
- java 多线程 发布订阅模式:发布者java.util.concurrent.SubmissionPublisher;订阅者java.util.concurrent.Flow.Subscriber
1,什么是发布订阅模式? 在软件架构中,发布订阅是一种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者).而是将发布的消息分为不同的类别,无需了解哪些订阅者(如果有的话 ...
- java多线程 生产者消费者模式
package de.bvb; /** * 生产者消费者模式 * 通过 wait() 和 notify() 通信方法实现 * */ public class Test1 { public static ...
- Java多线程系列——从菜鸟到入门
持续更新系列. 参考自Java多线程系列目录(共43篇).<Java并发编程实战>.<实战Java高并发程序设计>.<Java并发编程的艺术>. 基础 Java多线 ...
- Java多线程编程中Future模式的详解
Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...
- Java多线程学习笔记--生产消费者模式
实际开发中,我们经常会接触到生产消费者模型,如:Android的Looper相应handler处理UI操作,Socket通信的响应过程.数据缓冲区在文件读写应用等.强大的模型框架,鉴于本人水平有限目前 ...
- java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-【费元星Q9715234】
java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-[费元星Q9715234] 说明如下,不懂的问题直接我[费元星Q9715234] 1.反射的意义在于不将xml tag ...
- Java多线程Future模式
Java多线程Future模式有些类似于Ajax的异步请求Future模式的核心在于:去除了主函数的等待时间,并使得原本需要等待的时间段可以用于处理其他业务逻辑 假设服务器的处理某个业务,该业务可以分 ...
- Java多线程--并行模式与算法
Java多线程--并行模式与算法 单例模式 虽然单例模式和并行没有直接关系,但是我们经常会在多线程中使用到单例.单例的好处有: 对于频繁使用的对象可以省去new操作花费的时间: new操作的减少,随之 ...
- 【多线程】java多线程实现生产者消费者模式
思考问题: 1.为什么用wait()+notify()实现生产者消费者模式? wait()方法可以暂停线程,并释放对象锁 notify()方法可以唤醒需要该对象锁的其他线程,并在执行完后续步骤,到了s ...
随机推荐
- 【专章】dp入门
动态规划(简称dp),可以说是各种程序设计中遇到的第一个坎吧,这篇博文是我对dp的一点点理解,希望可以帮助更多人dp入门. ***实践是检验真理的唯一标准,看再多文章不如自己动手做几道!!!*** 先 ...
- [bzoj1066] [SCOI2007] 蜥蜴 - 网络流
在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外. 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个 ...
- http://codeforces.com/contest/402/problem/E
E. Strictly Positive Matrix time limit per test 1 second memory limit per test 256 megabytes input s ...
- php使用PHPMailer邮件类发送邮件
PHPMailer是一个用于发送电子邮件的PHP函数包.它提供的功能包括:*.在发送邮时指定多个收件人,抄送地址,暗送地址和回复地址*.支持多种邮件编码包括:8bit,base64,binary和qu ...
- CPU工作方式、多核心、超线程技术详解[转贴]
CPU是一台电脑的灵魂,决定电脑整体性能.现在的主流CPU都是多核的,有的运用了多线程技术(Hyper-threading,简称HT).多核可能还容易理解些,相信不少玩家都能说出个所以然.但超线程是个 ...
- Template7插入动态模板
要完成的效果如下图 其中下面添加出来的订单号和订单总价可以看作是接口请求的数据 实现步骤: 1 下载template7:https://github.com/nolimits4web/template ...
- JavaScript链式调用
1.什么是链式调用? 这个很容易理解,例如 $('text').setStyle('color', 'red').show(); 一般的函数调用和链式调用的区别:链式调用完方法后,return thi ...
- List之Union(),Intersect(),Except() 即并集,交集,差集运算。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- 【Vue】浅谈Vue(一):从模板语法数据绑定、指令到计算属性
写在前面 今年前端届比较有意思,从大漠穷秋发表文章比较angular和vue,继而致歉vue作者.社区,从谷歌辞去Angular Developer PM in China一职并且呼吁大家停止各种无谓 ...
- Mac使用nginx+rtmp服务器
一.安装Homebrow 已经安装了brow的可以直接跳过这一步.执行命令 ruby -e "$(curl -fsSL https://raw.githubusercontent.com/H ...