介绍
在多线程程序设计中Master worker 模式是常用的并行模式之一,核心思想是由两类进程协助完成的,Master 进程负责接收和分配任务并处理保存结果集,Worker 负责处理任务, 并把结果返回给Master 进程. 这类设计模式最大的好处是 将一个大任务分配成若干个小任务并行执行。可见master-worker 模式适合与将大任务化成小任务并行执行的情况,各个小任务基本并行独立运行,最终提供效率。
示例
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:设置不同的线程数耗时不同