Master And Works 模式是一种并发设计模式,主要用于分发相应,用以提高吞吐量
我觉得在模式上,Master可以粗略的类比为Spring前端控制器Dispatcher Servlet,它用于分发请求,具体操作是留给具体(Workers)handler去处理。
首先呢,先归纳一下Master所需要的东西:
- Master对象内含一个队列属性,该队列用于存放需要执行的任务事件,根据需求可以考虑阻塞、无阻塞、有界、无界队列(一般不推荐),但本例中采用无界无阻塞队列线程安全队列ConcurrentLinkedQueue来查看相关介绍
- 需要一个存放具体干事儿Workers/Slaves的集合,我采用的效率比较高的HashMap来存放,为什么可以用HashMap,因为此处HashMap不存在多线程来访问,能够调用它的只有Master
- 每一个Workers/Slaves执行完成所返回的结果集,这个会被每一个worker并发写入所以我这里采用ConcurrentHashMap来存放
- 一个自定义线程池,这里我使用的newFixedThreadPool,关于线程池和参数介绍,可以参考这篇ThreadPool
以上4点为此模式所需要的一般通用属性。理解每一个属性的意义,对于理解整个模式有很大帮助。
!!下面我们开始讨论Master里面所需要的方法:
- 根据第一个属性,我们知道此队列存放任务事件,那么我们肯定需要一个方法添加任务(而取任务并执行应该由worker来完成)
/**
- 将接受到的任务放入任务存储容器中
*/
public void submitMission(Mission mission){
....
}
- 一个处理所有Worker返回值的聚合方法
public Object getResult(){
....
}
- 既然Worker是具体执行者,那么他肯定是并发处理,所以Worker肯定是实现了Runnable接口的。且Master里面的自定义线程池就是来启动这些Worker的,我们需要一个启动所有Worker的方法
/**
- Master中的执行任务等于启动所有线程
*/
public void executeMission(){
....
executorService.execute(...);
}
- 既然有启动方法我们也就自然需要一个判断方法判断线程是否执行结束
public boolean isTerminal(){
....
}
然后呢,归纳一下Worker所需要的东西:
- 第一个参数不是必须参数,identity用来表示是哪一个worker
- 需要有一个和Master属性一样的ConcurrentLinkedQueue队列
- 需要有一个和Master属性一样的ConcurrentHashMap来存放
下面就是方法了:
- 首先就是run方法了(下面是一个模版)
@Override
public void run() {
while (true){
MarathonMission mission = missionQueue.poll();
if (mission == null) {
break;
}
//下面是一个处理业务的核心方法
Object result = handle(mission);
resultMap.put((long)mission.getOrder(),result);
}
}
- handle是我们处理业务的核心方法,我们将它抽取出来
public abstract Object handle(MarathonMission mission);
https://github.com/teneous/javaDemo.git 里面的concurrency/src/masterwork可下载代码(写的不咋地,应该意思是表达清楚了的)