Java Master-Worker模式

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

Java Master-Worker模式_第1张图片

整理流程就是上图所表示的,这里涉及到了多个线程同时操作任务。所以,我们需要用到 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 linkedQueue = new ConcurrentLinkedQueue<>();

    /**
     * 存放执行结果集合
     */
    private ConcurrentHashMap resultMap = new ConcurrentHashMap<>();

    /**
     * 当前开启的线程集合。
     */
    private HashMap 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 entry : map.entrySet()) {
            entry.getValue().start();
        }
    }

    /**
     * 判断所有线程是否都执行完成。
     *
     * @return
     */
    public boolean isComplete() {
        for (Map.Entry entry : map.entrySet()) {
            if (entry.getValue().getState() != Thread.State.TERMINATED) {
                return false;
            }
        }
        return true;
    }

    public ConcurrentHashMap getResultMap() {
        return resultMap;
    }
}

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

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

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

public class Worker implements Runnable {

    private ConcurrentLinkedQueue queue;
    private ConcurrentHashMap resultMap;

    public void setQueue(ConcurrentLinkedQueue queue) {
        this.queue = queue;
    }

    public void setResultMap(ConcurrentHashMap 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 map = master.getResultMap();
                for (Map.Entry en :
                        map.entrySet()) {
                    System.out.println("result : " + en.getKey() + " , " + en.getValue());
                }
                break;
            }
        }
    }
}

执行结果

Java Master-Worker模式_第2张图片

你可能感兴趣的:(Java)