標籤:link min nts value protected mem entryset prot interrupt
Java多線程Master-Worker模式,多適用於需要大量重複工作的情境中。
例如:使用Master-Worker計算0到100所有數位立方的和
1.Master接收到100個任務,每個任務需要0到100中每個數位立方,這裡為了效果,每個任務再sleep一秒,
Master需要將這些任務放到一個支援高並發的非阻塞隊列queue中如:ConcurrentLinkedQueue<E>。
2.Master建立10個worker去執行這100個任務,並準備一個支援高並發且安全執行緒的hashMap作為結果集的容器如:ConcurrentHashMap。
3.每個worker需要迴圈的從queue中擷取任務然後執行,執行完畢後把結果放到hashMap中,直到queue為空白,所有任務執行完畢後退出。
4.Master迴圈判斷結果集hashMap中是否有已經執行完畢的結果,如果有就使用,使用完畢就立即移除該結果,直到所有的線程都退出。
5.所有任務執行完畢,Master也處理完所有任務的結果,程式結束
Master不需要等待所有的任務執行完畢就可以處理已完成的任務結果,Master和worker可以同時進行工作,這樣節省了大量等待worker執行結束的時間
Master源碼
package masterWorker;import java.lang.Thread.State;import java.util.Collection;import java.util.HashMap;import java.util.Map;import java.util.Map.Entry;import java.util.Queue;import java.util.Set;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.ConcurrentLinkedQueue;import org.junit.Test;public class Master {public static void main(String[] args) {long befor = System.currentTimeMillis();//任務隊列Queue<Integer> taskQueue = new ConcurrentLinkedQueue<>();//工人mapMap<String,Thread> workers = new HashMap<>();//結果集Map<String,Long> resultMap = new ConcurrentHashMap<>();//最終結果long result = 0;//提交100個任務for (int i = 0; i < 100; i++) {taskQueue.add(i);}//添加10個工人for (int i = 0; i < 10; i++) {workers.put(i+"", new Thread(new Worker(taskQueue,resultMap),"工人"+i));}//啟動所有工人線程Collection<Thread> threads = workers.values();for (Thread thread : threads) {thread.start();}while(resultMap.size() > 0 || !isComplete(workers)){Set<String> keySet = resultMap.keySet();//每次從resultMap中取一個結果出來進行使用String key = null;for (String string : keySet) {if(string != null){key = string;break;}}Long value = null;if(key != null){value = resultMap.get(key);}//能取到結果就使用,沒有結果繼續迴圈if(value != null){//擷取到一個運算結果就使用result = result+value;//使用後從結果集中移除resultMap.remove(key);}}long after = System.currentTimeMillis();System.out.println("結果耗時:"+(after - befor));System.out.println(result);}/** * 判斷所有的工人是否已經完成工作 * @param workers * @return */private static boolean isComplete(Map<String,Thread> workers){for (Entry<String, Thread> entry : workers.entrySet()) {if(entry.getValue().getState() != State.TERMINATED){return false;}}return true;}@Testpublic void test() throws InterruptedException{long befor = System.currentTimeMillis();long result = 0;for (int i = 0; i < 100; i++) {long cube = i*i*i;result = result+cube;Thread.sleep(100);}long after = System.currentTimeMillis();System.out.println("結果耗時:"+(after - befor));System.out.println(result);}}
Worker源碼
package masterWorker;import java.util.Map;import java.util.Queue;public class Worker implements Runnable{private Queue<Integer> queue;private Map<String,Long> resultMap;public Worker(Queue<Integer> queue,Map<String,Long> resultMap) {this.queue = queue;this.resultMap = resultMap;}@Overridepublic void run() {//不斷迴圈從隊列中取出任務進行運算,直到隊列為空白while(true){if(queue.peek() != null){String name = Thread.currentThread().getName();int poll =(int) queue.poll();long result = poll*poll*poll;try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}resultMap.put(poll+"", result);System.out.println(name+"完成"+poll+"的運算,結果為:"+result);}else{break;}}}}
經典的Master-Worker源碼執行個體
package masterWorker.classics;import java.util.Map; import java.util.Set; public class Main { /** * @param args */ public static void main(String[] args) { //固定使用5個Worker,並指定Worker Master m = new Master(new PlusWorker(), Runtime.getRuntime().availableProcessors()); //提交100個子任務 for(int i=0;i<100;i++){ m.submit(i); } //開始計算 m.execute(); int re= 0; //儲存最終結算結果 Map<String ,Object> resultMap =m.getResultMap(); //不需要等待所有Worker都執行完成,即可開始計算最終結果 while(resultMap.size()>0 || !m.isComplete()){ Set<String> keys = resultMap.keySet(); String key =null; for(String k:keys){ key=k; break; } Integer i =null; if(key!=null){ i=(Integer)resultMap.get(key); } if(i!=null){ //最終結果 re+=i; } if(key!=null){ //移除已經被計算過的項 resultMap.remove(key); } } System.out.println(re); } } package masterWorker.classics;import java.util.Map; import java.util.Queue; public class Worker implements Runnable{ //任務隊列,用於取得子任務 protected Queue<Object> workQueue; //子任務處理結果集 protected Map<String ,Object> resultMap; public void setWorkQueue(Queue<Object> workQueue){ this.workQueue= workQueue; } public void setResultMap(Map<String ,Object> resultMap){ this.resultMap=resultMap; } //子任務處理的邏輯,在子類中實現具體邏輯 public Object handle(Object input){ return input; } @Override public void run() { while(true){ //擷取子任務 Object input= workQueue.poll(); if(input==null){ break; } //處理子任務 Object re = handle(input); resultMap.put(Integer.toString(input.hashCode()), re); } } } package masterWorker.classics;public class PlusWorker extends Worker { @Override public Object handle(Object input) { Integer i =(Integer)input; return i*i*i; } } package masterWorker.classics;import java.util.HashMap;import java.util.Map;import java.util.Queue;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.ConcurrentLinkedQueue;public class Master {// 任務隊列protected Queue<Object> workQueue = new ConcurrentLinkedQueue<Object>();// Worker進程隊列protected Map<String, Thread> threadMap = new HashMap<String, Thread>();// 子任務處理結果集protected Map<String, Object> resultMap = new ConcurrentHashMap<String, Object>();// 是否所有的子任務都結束了public boolean isComplete() {for (Map.Entry<String, Thread> entry : threadMap.entrySet()) {if (entry.getValue().getState() != Thread.State.TERMINATED) {return false;}}return true;}// Master的構造,需要一個Worker進程邏輯,和需要Worker進程數量public Master(Worker worker, int countWorker) {worker.setWorkQueue(workQueue);worker.setResultMap(resultMap);for (int i = 0; i < countWorker; i++) {threadMap.put(Integer.toString(i),new Thread(worker, Integer.toString(i)));}}// 提交一個任務public void submit(Object job) {workQueue.add(job);}// 返回子任務結果集public Map<String, Object> getResultMap() {return resultMap;}// 開始運行所有的Worker進程,進行處理public void execute() {for (Map.Entry<String, Thread> entry : threadMap.entrySet()) {entry.getValue().start();}}}
Java多線程Master-Worker模式