Java Master-Worker模式

来源:互联网 发布:在线个人相册php源码 编辑:程序博客网 时间:2024/06/05 18:58

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

这里写图片描述

整理流程就是上图所表示的,这里涉及到了多个线程同时操作任务。所以,我们需要用到 java.util.concurrent 包下的几个线程安全的集合。

ConcurrentLinkedQueue , ConcurrentHashMap 

模拟基础的任务对象:

public class Task {    private int id;    private String name;    public Task(int id, String name) {        this.id = id;        this.name = name;    }    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;    }}

Master 对象,负责所有任务的分配,归纳。

public class Master {    /**     * 需要执行的任务队列。     */    private ConcurrentLinkedQueue<Task> linkedQueue = new ConcurrentLinkedQueue<>();    /**     * 存放执行结果集合     */    private ConcurrentHashMap<String, String> resultMap = new ConcurrentHashMap<>();    /**     * 当前开启的线程集合。     */    private HashMap<String, Thread> map = new HashMap<>();    public Master(int count) {        Worker worker = new Worker();        worker.setQueue(linkedQueue);        worker.setResultMap(resultMap);        for (int i = 0; i < count; i++) {            map.put("线程" + (i + 1), new Thread(worker));        }    }    /**     * 添加任务     *     * @param task     */    public void add(Task task) {        linkedQueue.add(task);    }    /**     * 执行任务     */    public void execute() {        for (Map.Entry<String, Thread> entry : map.entrySet()) {            entry.getValue().start();        }    }    /**     * 判断所有线程是否都执行完成。     *     * @return     */    public boolean isComplete() {        for (Map.Entry<String, Thread> entry : map.entrySet()) {            if (entry.getValue().getState() != Thread.State.TERMINATED) {                return false;            }        }        return true;    }    public ConcurrentHashMap<String, String> getResultMap() {        return resultMap;    }}

Master 中需要有三个私有集合变量,分别存储当前所有任务,最后执行的任务结果,以及当前开启的线程数,达到任务的分配以及总结。

Thread.State.TERMINATED 表示当前线程执行完成。

Worker 根据我们上面的流程图,我们可以看出 worker 对象其实就是一个线程。用来处理 Master 分配的每一个单元任务的。

public class Worker implements Runnable {    private ConcurrentLinkedQueue<Task> queue;    private ConcurrentHashMap<String, String> resultMap;    public void setQueue(ConcurrentLinkedQueue<Task> queue) {        this.queue = queue;    }    public void setResultMap(ConcurrentHashMap<String, String> resultMap) {        this.resultMap = resultMap;    }    @Override    public void run() {        while (true) {            Task task = queue.poll();   // poll 获取头元素 并删除。 peek 获取头元素不删除。            if (task == null) {                break;            }            try {                TimeUnit.SECONDS.sleep(3);// 休眠3秒                resultMap.put("id:" + task.getId(), task.getName());            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}

Worker 中 添加公开的 set 方法,用于获取 Master 中的任务队列,存储结果集合的引用。主要在 run() 方法中执行任务处理操作,这里也是模拟一个耗时操作。
因为我们的工作线程数是有限的,但是任务数量可能远远超过工作线程数量。所以这里利用 while(true) 去进行持续的获取任务队列中的任务。
代码中也有部分注释,当队列中的所有任务处理完成之后,queue.poll() 获取的任务为 null, 那么就跳出当前循环,结束线程。

Client端 调用代码:

public class Client {    public static void main(String[] args) {        int count = Runtime.getRuntime().availableProcessors();// 当前设备所支持的线程数。        Master master = new Master(count);        for (int i = 0; i < (count * 2); i++) {            Task task = new Task(i + 1, "name" + (i + 1));            master.add(task);        }        System.out.println(count);        long start = System.currentTimeMillis();        master.execute();        while (true) {        // 等待所有任务执行完成。            if (master.isComplete()) {                Map<String, String> map = master.getResultMap();                for (Map.Entry<String, String> en :                        map.entrySet()) {                    System.out.println("result : " + en.getKey() + " , " + en.getValue());                }                break;            }        }    }}

执行结果

这里写图片描述

0 0
原创粉丝点击