Java Thread系列(九)Master-Worker模式
Java Thread系列(九)Master-Worker模式
Master-Worker模式是常用的并行设计模式.
一、Master-Worker 模式核心思想
Master-Worker 系统由两个角色组成,Master 和 Worker,Master 负责接收和分配任务,Worker 负责处理子任务。任务处理过程中,Master 还负责监督任务进展和 Worker 的健康状态;Master 将接收 Client 提交的任务,并将任务的进展汇总反馈给 Client。各角色关系如下图:
二、Master-Worker 实现
(1) Master
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
public class Master {
    //1. 应该有一个容器存放任务列表,这个容器需要支持高并发操作
    private ConcurrentLinkedDeque<Task> taskQueue = new ConcurrentLinkedDeque<Task>();
    //2. 应该有一个容器存放worker
    private HashMap<String, Thread> workers = new HashMap<String, Thread>();
    //3. 应该有一个容器存放结果集,这个容器需要支持高并发操作
    private ConcurrentHashMap<String, Object> resultMap = new ConcurrentHashMap<String, Object>();
    //4. 构造函数
    public Master (Worker worker, int threadCount) {
        //将任务列表和结果集传递给worker
        worker.setTaskQueue(taskQueue);
        worker.setResultMap(resultMap);
        //初始化worder列表
        for (int i = 0; i < threadCount; i++) {
            workers.put("worker-" + i, new Thread(worker));
        }
    }
    public Master (Worker worker) {
        this(worker, Runtime.getRuntime().availableProcessors());
    }
    //5. 提交任务
    public void submit (Task task) {
        taskQueue.add(task);
    }
    //6. 执行方法 开启所有的线程
    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 += (int)me.getValue();
        }
        return ret;
    }
}
(2) Worker
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
public class Worker implements Runnable {
    private ConcurrentLinkedDeque<Task> taskQueue;
    private ConcurrentHashMap<String, Object> resultMap;
    @Override
    public void run() {
        while (true) {
            Task task = taskQueue.poll();
            if (task == null) break;
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //返回结果集
            resultMap.put(Integer.toString(task.getId()), handle(task));
        }
    }
    private Object handle(Task task) {
        return task.getCount();
    }
    public void setTaskQueue(ConcurrentLinkedDeque<Task> taskQueue) {
        this.taskQueue = taskQueue;
    }
    public void setResultMap(ConcurrentHashMap<String, Object> resultMap) {
        this.resultMap = resultMap;
    }
}
(3) Task
public class Task {
    private int id;
    private String name;
    private int count;
    public Task() {}
    public Task(int id, String name, int count) {
        this.id = id;
        this.name = name;
        this.count = count;
    }
    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 getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count = count;
    }
    @Override
    public String toString() {
        return "Task{" + "id=" + id + ", name='" + name + '\'' +
                ", count=" + count + '}';
    }
}
(4) 测试
Master master = new Master(new Worker(), 1);
for (int i = 1; i <= 100; i++) {
    master.submit(new Task(i, "task-" + i ,i));
}
master.execute();
long t1 = System.currentTimeMillis();
while (true) {
    if (master.isComplete()) {
        long t = System.currentTimeMillis() - t1;
        System.out.printf("执行结果:%s;执行时间:%s", master.getResult(), t);
        break;
    }
}
每天用心记录一点点。内容也许不重要,但习惯很重要!
Java Thread系列(九)Master-Worker模式的更多相关文章
- Java Thread系列(十)Future 模式
		Java Thread系列(十)Future 模式 Future 模式适合在处理很耗时的业务逻辑时进行使用,可以有效的减少系统的响应时间,提高系统的吞吐量. 一.Future 模式核心思想 如下的请求 ... 
- Java Thread系列(十)生产者消费者模式
		Java Thread系列(十)生产者消费者模式 生产者消费者问题(producer-consumer problem),是一个多线程同步问题的经典案例.该问题描述了两个共亨固定大小缓冲区的线程-即所 ... 
- Java Thread系列(七)死锁
		Java Thread系列(七)死锁 当线程需要同时持有多个锁时,有可能产生死锁.考虑如下情形: 线程 A 当前持有互斥所锁 lock1,线程 B 当前持有互斥锁 lock2.接下来,当线程 A 仍然 ... 
- java多线程系列(九)---ArrayBlockingQueue源码分析
		java多线程系列(九)---ArrayBlockingQueue源码分析 目录 认识cpu.核心与线程 java多线程系列(一)之java多线程技能 java多线程系列(二)之对象变量的并发访问 j ... 
- Java Thread系列(四)线程通信
		Java Thread系列(四)线程通信 一.传统通信 public static void main(String[] args) { //volatile实现两个线程间数据可见性 private ... 
- Java Thread系列(五)synchronized
		Java Thread系列(五)synchronized synchronized锁重入 关键字 synchronized 拥有锁重入的功能,也就是在使用 synchronized 时,当线程等到一个 ... 
- Java Thread系列(三)线程安全
		Java Thread系列(三)线程安全 一.什么是线程安全 线程安全概念:当多个线程访问某一个类(对象或方法)时,这个类始终都能表现出正确的行为,那么这个类(对象或方法)就是线程安全的. 线程安全来 ... 
- Java Thread系列(二)线程状态
		Java Thread系列(二)线程状态 一.线程的五种状态 新建状态(New):新创建了一个线程对象,尚未启动. 就绪状态(Runnable):也叫可运行状态.线程对象创建后,其他线程调用了该对象的 ... 
- Java Thread系列(一)线程创建
		Java Thread系列(一)线程创建 Java 中创建线程主要有三种方式:继承 Thread.实现 Runnable 接口.使用 ExecutorService.Callable.Future 实 ... 
随机推荐
- linux bash shell 判断目录是否为空的函数
			#!/bin/sh ##方法一 判断输出字符数统计为0 is_empty_dir(){ |wc -w` } ##方法二 判断输出string为空 #is_empty_dir(){ # ` ] #} t ... 
- 使用 Windows 10 中的加速度计(Accelerometer,重力传感器)
			在做 UWP 应用开发的时候还有什么理由可以用到加速度计呢?场景很多啦,比如做游戏,做类似 Surface Hub 那种一边旋转,一边所有内容跟着一起转的效果. Windows 10 UWP 中的加速 ... 
- HDU 4123 Bob’s Race(RMQ)
			题意是说给出一棵树,N(10^5)个顶点,以及每条边的权值,现在需要选择连续的K个点(顶点编号连续),可以被选出来的条件是: 若d[i]代表顶点i到树上其他点的距离的最大值,使得区间[a, b]的d值 ... 
- Python 字典(Dictionary) update()方法
			refer to: http://www.runoob.com/python/att-dictionary-update.html 
- hadoop之 Hadoop 2.x HA 、Federation
			HDFS2.0之HA 主备NameNode: 1.主NameNode对外提供服务,备NameNode同步主NameNode元数据,以待切换: 2.主NameNode的信息发生变化后,会将信息写到共享数 ... 
- bzoj 4823 [Cqoi2017]老C的方块——网络流
			题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4823 一个不合法方案其实就是蓝线的两边格子一定选.剩下两部分四相邻格子里各选一个. 所以这个 ... 
- oracle undo表空间大小修改
			redhat:清空回收站 rm -rf /home/登录用户名/.Trash 例子:rm -rf /home/.Trash-root df命令可以显示目前所有文件系统的可用空间及使用情形: 例子:d ... 
- emacs之配置symbol浏览界面
			由于ecb的method-buffer不能更新,因此抛弃ecb,speedbar的method也不能更新,换imenu-tree 使用el-get install安装imenu-tree imenu- ... 
- java 线程池 ExeutorService
			Java线程池 ExecutorService 原文:https://blog.csdn.net/suifeng3051/article/details/49443835/ 本篇主要涉及到的是java ... 
- [Java.web]MVC 案例-开发用户模块(注册)
			代码下载 生成后的 user.xml 路径在 X:\day09_user\WebRoot\WEB-INF\classes\users.xml 使用测试 在 day09 项目上右键 -> Run ... 
