Java 併發模式之Master-Worker
注:本文摘記於《Java程式效能優化》一書,轉載請註明出處。
Master-Worker模式的核心思想是:系統有兩類程式協作工作,即Master程式和Worker程式。Master程式負責接收和分配任務,Worker程式負責處理子任務。當各個Worker程式將子任務處理完後,將結果返回給Master程式,由Master程式做歸納和彙總,從而得到系統的最終結果。其處理過程如下圖:
Master-Worker模式的好處,它能夠將一個大任務分解成若干個小任務,並行執行,從而提高系統的吞吐量。而對於系統請求者Client來說,任務一旦提交,Master程式會分配任務並立即返回,並不會等待系統全部處理完成後再返回,其處理過程是非同步的。因此Client不會出現等待現象。
1.Master-Worker模式結構
Master-Worker模式的結構相對比較簡單,此處將給出一個簡明的實現方式。如下圖,Master程式為主要程式,它維護了一個Worker程式佇列、子任務佇列和子結果集。Worker程式佇列中的Worker程式,不停地從人物佇列中提取要處理的子任務,並將子任務的處理結構寫入結果集。
注意:Master-Worker模式是一種使用多執行緒進行資料處理的結構。多個Worker程式協作處理使用者請求,Master程式負責維護Worker程式,並整合最終處理結果。
Master-Worker模式的主要參與者如下圖表4.2所示:
2.Master-Worker的程式碼實現
基於以上所述的設計思路,這裡給出一個簡易的Master-Worker框架。其中Master部分的實現程式碼如下:
package com.roc.masterworker;
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>();
/**
* 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();
}
}
/**
* 是否所有的子任務都結束了
*/
public boolean isComplete()
{
for (Map.Entry<String, Thread> entry : threadMap.entrySet())
{
if (entry.getValue().getState() != Thread.State.TERMINATED)
{
return false;
}
}
return true;
}
}
對應的Worker程式實現如下:
package com.roc.masterworker;
import java.util.Map;
import java.util.Queue;
public class Worker implements Runnable
{
/**
* 任務佇列,用於取得子任務
*/
protected Queue<Object> workerQueue;
/**
* 子任務處理結果集
*/
protected Map<String, Object> resultMap;
public void setResultMap(Map<String, Object> resultMap)
{
this.resultMap = resultMap;
}
public void setWorkQueue(Queue<Object> workeQueue)
{
this.workerQueue = workeQueue;
}
/**
* 子任務的處理邏輯,在子類中實現具體邏輯
*/
public Object handle(Object input)
{
return input;
}
@Override
public void run()
{
while (true)
{
// 獲取子任務
Object input = workerQueue.poll();
if (input == null)
{
break;
}
// 處理子任務
Object result = handle(input);
// 將處理結果寫入結果集
resultMap.put(Integer.toString(input.hashCode()), result);
}
}
}
以上兩段程式碼已經展示了Master-Worker的框架全貌。應用程式中通過過載Worker.handle()方法實現應用層邏輯。
注意:Master-Worker模式是一種將序列化任務並行化的方法,被分解的子任務在系統中可以被並行處理。同時,如果有需要,Master程式不需要等待所有子任務都完成計算,就可以根據已有的部分結果集計算最終結果。
3.應用舉例
現應用這個Master-Worker框架,實現一個計算立方體和的應用並計算1~100的立方體和。即13+23+······+1003。任務分解圖如圖4.7所示。
計算任務被分解為100個子任務,每個子任務僅用於計算單獨的立方和。Master產生固定個數的Worker,來處理所有這些子任務。Worker不斷地從任務集合中取得這些計算立方和的子任務,並將計算結果返回給Master。Master負責將所有Worker的任務結果進行累加,從而產生最終的立方和。在整個計算過程中,Master與Worker的執行也是完全非同步的,Master不必等到所有的Worker都執行完後,就可以進行求和操作,即,Master在獲得部分子任務結果集時,就已經可以開始對最終結果進行計算,從而進一步提高系統的併發度和吞吐量。
Worker物件在應用層的程式碼實現如下:
package com.roc.masterworker.test;
import java.util.Map;
import java.util.Set;
import com.roc.masterworker.Master;
public class Test
{
public static void main(String[] args)
{
// 使用5個Worker,並指定Worker
Master m = new Master(new PlusWorker(), 5);
// 提交100個子任務
for (int i = 0; i < 100; i++)
{
m.submit(i);
}
// 開始計算
m.execute();
// 最終計算結果儲存於此
int result = 0;
Map<String, Object> resultMap = m.getResultMap();
String key = null;
Integer i = null;
Set<String> keys = null;
while (resultMap.size() > 0 || !m.isComplete())
{
// 不需要等待所有Worker都執行完,即可開始計算最終結果
keys = resultMap.keySet();
for (String k : keys)
{
key = k;
break;
}
if (key != null)
{
i = (Integer) resultMap.get(key);
}
if (i != null)
{
// 最終結果
result += i;
}
if (key != null)
{
// 移除已經被計算過得項
resultMap.remove(key);
}
}
System.out.println("-->result:" + result);;
}
}
在主函式中,首先通過Master類建立5個Worker工作程式和Worker工作例項PlusWorker。在提交了100個子任務後,便開始子任務的計算。這些子任務,由生成的5個Worker程式共同完成。Master並不等待所有的Worker執行完畢,就開始訪問子結果集進行最終結果的計算,直到子結果集中所有的資料都被處理,並且5個活躍的Worker程式全部終止,才給出最終計算結果。
原始碼下載地址:名字為Master-Worker
相關文章
- PHP 併發程式設計之 Master-Worker 模式PHP程式設計AST模式
- Master-Worker 模式AST模式
- Master-Worker模式AST模式
- 「Golang成長之路」併發之併發模式Golang模式
- java併發之synchronizedJavasynchronized
- Java併發之ExecutorJava
- java併發之CopyOnWriteArrayListJava
- 「Golang成長之路」併發之併發模式篇Golang模式
- Java併發設計模式--不可變模式(immutable)Java設計模式
- Java併發包之 CopyOnWriteArrayListJava
- Java併發之ConcurrentHashMapJavaHashMap
- Java併發(二十三)----同步模式之保護性暫停Java模式
- java併發之ConcurrentLinkedQueueJava
- java併發之hashmap原始碼JavaHashMap原始碼
- Java併發之AQS原理剖析JavaAQS
- Java併發之AQS詳解JavaAQS
- Java併發系列之volatileJava
- Java 併發包之CountDownLatch、CyclicBarrierJavaCountDownLatch
- Java併發之顯式鎖Java
- Java之併發三問題Java
- Java併發:深入淺出AQS之獨佔鎖模式原始碼分析JavaAQS模式原始碼
- Java併發程式設計---java規範與模式下的併發程式設計1.1Java程式設計模式
- Java併發程式設計之Java CAS操作Java程式設計
- Java併發之等待/通知機制Java
- java併發面試常識之copyonwriteJava面試
- Java併發之CompletionService詳解Java
- java併發之SynchronousQueue實現原理Java
- Java併發程式設計之synchronizedJava程式設計synchronized
- Java高併發之CyclicBarrier簡介Java
- Java併發之Executor + Callable + FutureJava
- Java併發之CountDownLatch、CyclicBarrier和SemaphoreJavaCountDownLatch
- Java併發指南9:AQS共享模式與併發工具類的實現JavaAQS模式
- 淺析Java併發中的單例模式Java單例模式
- java併發筆記之java執行緒模型Java筆記執行緒模型
- 【Java系列】Java併發之 Race Condition and Critical SectionJava
- Java併發之同步器設計Java
- JAVA併發之阻塞佇列淺析Java佇列
- Java高併發之synchronized關鍵字Javasynchronized