并发程序模式(二)—MasterWorker

来源:互联网 发布:海文网络计划 编辑:程序博客网 时间:2024/06/07 01:58
一.MasterWorker模式
 1)有两个类协同完成一组任务
 2)Master进程:维护一个Worker队列,和一个任务队列BlockingQueue,Master进程负责接受这组任务
 3)Worker进程:负责执行队列中的一个任务
 4)Master—Worker模式的精髓在于对任务的合理分割,把一个大任务,拆成小任务加到Master的任务队列,用Worker线程执行
public class Master {    private Queue<Object> tashQueue = new ConcurrentLinkedQueue<Object>();  //任务队列    private Map<Integer,Thread> workerMap = new HashMap();                    //worker的队列    private Map<String,Object> resultMap = new ConcurrentHashMap();                    //worker的结果集        public Map<String, Object> getResultMap() {    //获取执行结果        return resultMap;    }    public Master(Worker worker,int count){        worker.setTashQueue(tashQueue);        worker.setResultMap(resultMap);        for(int i=0;i<count;i++){        //生成线程            this.workerMap.put(i,new Thread(worker,i+""));        }    }        public void submit(Object job){ //主函数分配好每个小任务将其提交给任务队列        this.tashQueue.add(job);    }        public void execute(){        for(Entry<Integer,Thread> en : workerMap.entrySet()){            en.getValue().start();   //开启每个worker线程        }    }        public boolean isComplete(){        for(Entry<Integer,Thread> en:workerMap.entrySet()){            if(en.getValue().getState()!=Thread.State.TERMINATED) // 判断每个worker线程都结束                return false;        }        return true;    }    }
public abstract class Worker implements Runnable {    private Queue<Object> taskQueue = new ConcurrentLinkedQueue<Object>();  //让所有worker线程共享Master传来的并发队列,是每个线程取到不同的任务    private Map<String,Object> resultMap = new ConcurrentHashMap();            //并发map,让多个线程向map增加结果        public void setTashQueue(Queue<Object> taskQueue) {        this.taskQueue = taskQueue;    }    public void setResultMap(Map<String, Object> resultMap) {        this.resultMap = resultMap;    }    @Override    public void run() { //不停地拿任务,执行        while(true){            Object task = this.taskQueue.poll();            if(task == null)                break;            Object result = this.handle(task);            this.resultMap.put(UUID.randomUUID().toString(), result);        }    }    abstract Object handle(Object input) ; //每个真实的worker的执行方法不同}
//计算1..100的立方和public static void main(String[] args) {    Worker worker = new Worker() {            @Override            Object handle(Object input) {                int i = (Integer)input;                try {                    Thread.sleep(100000);                } catch (InterruptedException e) {                }                return i*i*i;            }        };        Master master = new Master(worker, 5); //开启5个worker线程        for(int i=1;i<=100;i++){            master.submit(i);    //分成100个独立计算立方的小任务        }        master.execute();        Map<String,Object> map = master.getResultMap();        int sum = 0;        while(map.size()>0||! master.isComplete()){            String key = null; //获取map的一个value,计算和,然后删除次对<k,v>,计算下一个            for(String k:map.keySet()){                key = k;                break;           //拿到一个value就跳出            }            if(key!=null){     //必须有key!=null,因为一开始线程可能还没返回结果,直接get(key)空指针                int i = (Integer)map.get(key);                sum += i;                map.remove(key);            }        }        System.out.println(sum);    }


0 0