生產消費模型-多生產者vs多消費者

使用場景:

      遊戲中多個玩家生產任務,服務器多線程處理任務, Netty工作線程收到客戶端傳來數據,生成任務後,加入到任務隊列中;

      遊戲服啓動後,創建多個消費線程,當有任務加入到隊列中,其中某個消費者取得任務並處理,1000個玩家在線玩耍,只有10個線程處理任務。


public abstract class BaseTask {

	
	public abstract void run();
}

任務管理器

public class MutiTaskManager {

	private MutiTaskManager(){
		
	}
	
	private final static MutiTaskManager instance = new MutiTaskManager();
	
	public static MutiTaskManager getInstance(){
		return instance;
	}
	
	//線程池
	private ExecutorService executor = null;
	
	//任務隊列
	private volatile Queue<BaseTask> taskQueue = new LinkedList<BaseTask>();
	
	//線程對象列表
	private List<MutiTaskExecutor> taskExecutors;
	
	//線程數量
	private int threadNum;
	
	private volatile Object signal = new Object();
	
	/**
	 * 初始化線程列表
	 * @param threadCnt
	 */
	public void init(int threadCnt){
		this.threadNum = threadCnt;
		taskExecutors = new ArrayList<MutiTaskExecutor>(threadNum);
		for(int i = 0; i < threadNum ; i ++){
			taskExecutors.add(new MutiTaskExecutor(signal));
		}
	}
	
	/**
	 * 添加任務
	 * @param task
	 */
	public void addTask(BaseTask task){
		synchronized(signal){
			taskQueue.add(task);
			signal.notify();
		}
	}
	
	/**
	 * 取出任務 
	 * @return
	 */
	public BaseTask popTask(){
		return taskQueue.poll();
	}
	
	public int getTaskSize(){
		return taskQueue.size();
	}
	
	/**
	 * 開啓服務,啓動線程池
	 */
	public void startService(){
		executor = Executors.newFixedThreadPool(threadNum);
		for(int i = 0; i < threadNum ; i ++){
			executor.execute(taskExecutors.get(i));
		}
	}
	
	public void stopService() throws Exception{
		for(int i = 0; i < threadNum ; i ++){
			taskExecutors.get(i).stopWork();
		}
		this.executor.shutdown();
	}
}


消費者

/**
 * 任務執行者
 * @author skymr
 *
 */
public class MutiTaskExecutor implements Runnable {

	private Object signal;
	private boolean isStarted = true;

	public MutiTaskExecutor(Object signal) {
		this.signal = signal;
	}

	@Override
	public void run() {
		BaseTask task = null;
		while (isStarted) {
			synchronized (signal) {
				task = MutiTaskManager.getInstance().popTask();
				if (task == null) {
					try {
						signal.wait();
					} catch (InterruptedException e) {
					}
					task = MutiTaskManager.getInstance().popTask();
				}
			}
			if (task != null) {
				try{
					task.run();
				}catch(Exception e){
					LogUtil.logException(e);
				}
			}
		}
	}
	
	public void stopWork(){
		this.isStarted = false;
	}
	
}


消息者的任務是一個無限循環中,判斷是否有新任務加入,如果有,執行任務,消費;如果沒有則進入等待(signal.wait()),直到接收到任務通知。

發佈了35 篇原創文章 · 獲贊 15 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章