在多线程程序设计中Master worker 模式是常用的并行模式之一,核心思想是由两类进程协助完成的,Master 进程负责接收和分配任务并处理保存结果集,Worker 负责处理任务, 并把结果返回给Master 进程. 这类设计模式最大的好处是 将一个大任务分配成若干个小任务并行执行。可见master-worker 模式适合与将大任务化成小任务并行执行的情况,各个小任务基本并行独立运行,最终提供效率。
分析过程:
1、既然Worker是具体的执行任务,那么Worker一定要实现Runnable接口。
2、Matser作为接受和分配任务,得先有个容器来装载用户发出的请求,在不考虑阻塞的情况下我们选择ConcurrentLinkedQueue作为装载容器。
3、Worker对象需要能从Master接收任务,它也得有Master ConcurrentLinkedQueue容器的引用。
4、Master还得有个容器需要能够装载所有的Worker,可以使用HashMap<String,Thread>。
5、Worker处理完后需要将数据返回给Master,那么Master需要有个容器能够装载所有worker并发处理任务的结果集。此容器需要能够支持高并发,所以最好采用ConcurrentHashMap<String,Object>。
6、同理由于Worker处理完成后将数据填充进Master的ConcurrentHashMap,那么它也得有一份ConcurrentHashMap的引用 。
下面看一个例子:
public class Master {
private List<Thread> threads = new ArrayList<Thread>();
private Queue taskQueue = new ConcurrentLinkedQueue();//线程安全Queue,频繁增加和删除
//线程安全Map,如果不需要key做业务的话也可以使用ConcurrentLinkedQueue
protected Map<Object, Object> resultMap = new ConcurrentHashMap<Object, Object>();
private AtomicInteger taskCount;//所有任务数量
protected AtomicInteger commitCount;//完成各项子任务后汇报以确定全部任务是否已完成
public Master(Worker worker, int workerCount) {
taskCount = new AtomicInteger();
commitCount = new AtomicInteger();
worker.setTaskQueue(taskQueue);
worker.setResultMap(resultMap);
worker.setCommitCount(commitCount);
for (int i = 0; i < workerCount; i++) {
threads.add(new Thread(worker));
}
}
public void submit(Object obj) {
taskQueue.add(obj);
taskCount.incrementAndGet();
}
public void execute() {
for (Thread t : threads) {
t.start();
}
}
public Map<Object, Object> getResultMap() {
return resultMap;
}
public boolean isComplete() {
return (commitCount.get() == taskCount.get()) && resultMap.isEmpty();
}
}
public abstract class Worker implements Runnable {
protected Queue taskQueue;
protected Map<Object, Object> resultMap;
protected AtomicInteger commitCount;
public void setTaskQueue(Queue taskQueue) {
this.taskQueue = taskQueue;
}
public void setResultMap(Map<Object, Object> resultMap) {
this.resultMap = resultMap;
}
public void setCommitCount(AtomicInteger commitCount) {
this.commitCount = commitCount;
}
@Override
public void run() {
for (Object input; (input = taskQueue.poll()) != null; ) {
Object result = handle(input);
resultMap.put(input, result);
commitCount.incrementAndGet();
}
}
protected abstract Object handle(Object input);
}
public class PlusWorker extends Worker {
@Override
protected Object handle(Object input) {
Integer obj = (Integer) input;
try {
Thread.sleep(new Random().nextInt(100));
} catch (InterruptedException e) {
e.printStackTrace();
}
return obj * obj * obj;
}
}
public class Main {
public static void main(String[] args) {
// 模拟计算立方和
int count = 500;
Master master = new Master(new PlusWorker(), 100);//相当于100个人每个人算一个立方和,最后Master算加法。
for (int i = 1; i <= count; i++) {
master.submit(i);
}
long start = System.currentTimeMillis();
master.execute();//开始执行
Map<Object, Object> resultMap = master.getResultMap();//对结果集进行操作
long total = 0;//最终结果
//只是为了作示例,出于简单考虑,没有使用阻塞、同步等控制
while (!master.isComplete()) {
for (Map.Entry<Object, Object> handleResult : resultMap.entrySet()) {
total += (Integer) handleResult.getValue();
resultMap.remove(handleResult.getKey());
}
try {Thread.sleep(10);} catch (Exception e) {}
}
System.out.println("耗时:" + (System.currentTimeMillis() - start));
System.out.println("合计结果:" + total);
}
}
运行结果:
耗时:326
合计结果:15687562500
ps:设置不同的线程数耗时不同
Master-Worker模式是一种将串行任务并行化的方案,被分解的子任务在系统中可以被并行处理,同时,如果有需要,Master进程不需要等待所有子任务都完成计算,就可以根据已有的部分结果集计算最终结果集。