多线程集成设计模式--MasterWorker模式讲解

Posted luzhouxiaoshuai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程集成设计模式--MasterWorker模式讲解相关的知识,希望对你有一定的参考价值。

Master-Worker模式是常用的并行模式之一,它的核心思想是,系统有两个进程协作工作:Master进程,负责接收和分配任务;Worker进程,负责处理子任务。当Worker进程将子任务处理完成后,结果返回给Master进程,由Master进程做归纳汇总,最后得到最终的结果。
一、什么是Master-Worker模式:
该模式的结构图:

Worker:用于实际处理一个任务;

Master:任务的分配和最终结果的合成;

Main:启动程序,调度开启Master。

 

注意点:

Master必须存在一个队列来存储客户端发送过来的任务,必须有一个队列,我们选择无阻塞无界队列

Worker实际处理任务的操作者,所以应该是线程,应该实现runnable接口

master应该有一个容器装所有的worker对象,不涉及到高并发,使用hashmap ,value就是worker对象

worker需要拥有master进程中的无阻塞无界队列的引用,用来获得任务进行处理

master是对worker处理的结果做归纳总结,所以需要有一个队列要保存worker处理的结果,要实现并发安全的ConcurrentHashMap

worker需要拥有ConcurrentHashMap的引用,把处理的结果存储在ConcurrentHashMap中,需要线程安全的

 

 

 

 Master-Worker模式是一种将串行任务并行化的方案。
更重要的是提供了一种变化的思想。

我们来看下面程序的代码:

package com.bjsxt.height.design015;

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;
    } 
    
}
package com.bjsxt.height.design015;

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;
    }



}
package com.bjsxt.height.design015;

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);
        /**
         * 初始化woker对象的个数,管理worker对象,开启100个worker对象,装到hashmap中
         * */
        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;
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
}
package com.bjsxt.height.design015;

import java.util.Random;

public class Main {

    public static void main(String[] args) {
        
        Master master = new Master(new Worker(), 20);
        
        Random r = new Random();
        for(int i = 1; i <= 100; 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;
            }
        }
        
    }
}

 

程序运行的结果是:

最终结果:54386, 执行时间:2500

将每个worker计算得到的price结果进行相加

相当的经典,这种设计模式就是将串行化的思想转换成并行化进行处理 

以上是关于多线程集成设计模式--MasterWorker模式讲解的主要内容,如果未能解决你的问题,请参考以下文章

多线程:多线程设计模式:生产者-消费模式

多线程和多进程模式有啥区别

Java多线程

多线程设计模式简介

多线程:多线程设计模式:Master-Worker模式

我的多线程—多线程与设计模式阅读笔记