簡體   English   中英

單個數據存儲的多個消息偵聽器。 高效的設計

[英]Multiple message listeners to single data store. Efficient design

我有一個由多個消息監聽器寫入的數據存儲。 這些消息監聽器中的每一個也可以在數百個單獨的線程中。

數據存儲是PriorityBlockingQueue因為它需要按時間戳對插入的對象進行排序。 為了有效地檢查項目隊列而不是循環隊列, 並發使用並發散列映射作為索引的形式。

private Map<String, SLAData> SLADataIndex = new ConcurrentHashMap<String, SLAData>();;
private BlockingQueue<SLAData> SLADataQueue;

問題1這是一個可接受的設計,或者我應該只使用單個PriorityBlockingQueue。

每個消息偵聽器都執行一個操作,這些偵聽器擴展到多個線程。

插入方法,以便插入兩者。

this.SLADataIndex.put(dataToWrite.getMessageId(), dataToWrite);
this.SLADataQueue.add(dataToWrite);

更新方法

this.SLADataIndex.get(messageId).setNodeId(
            updatedNodeId);

刪除方法

SLATupleData data = this.SLADataIndex.get(messageId);
//remove is O(log n)
this.SLADataQueue.remove(data);
// remove from index
this.SLADataIndex.remove(messageId);

問題二使用這些方法這是最有效的方法嗎? 它們通過另一個對象圍繞它們進行包裝以進行錯誤處理。

問題三使用並發HashMap和BlockingQueue這是否意味着這些操作是線程安全的? 我不需要使用鎖定對象?

問題四當多個線程和監聽器調用這些方法而沒有任何類型的同步塊時,它們是否可以由不同的線程或監聽器同時調用?

問題1這是一個可接受的設計,或者我應該只使用單個PriorityBlockingQueue。

當然你應該嘗試使用單個Queue 保持兩個集合同步將需要更多的同步復雜性並擔心代碼。

你為什么需要Map 如果它只是調用setNodeId(...)那么我會讓處理線程在從Queue拉出時自己做。

// processing thread
while (!Thread.currentThread().isInterrupted()) {
   dataToWrite = queue.take();
   dataToWrite.setNodeId(myNodeId);
   // process data
   ...
}

問題二使用這些方法這是最有效的方法嗎? 它們通過另一個對象圍繞它們進行包裝以進行錯誤處理。

當然,這似乎很好,但是,再次,你需要做一些同步鎖定,否則你將遇到競爭條件,使2個集合保持同步。

問題三使用並發HashMap和BlockingQueue這是否意味着這些操作是線程安全的? 我不需要使用鎖定對象?

這兩個類( ConcurrentHashMapBlockingQueue實現)都是線程安全的,是的。 但是因為有兩個,你可以有一個競爭條件,其中一個集合已經更新但另一個沒有。 最有可能的是,您必須使用鎖定對象來確保兩個集合都正確保持同步。

問題四當多個線程和監聽器調用這些方法而沒有任何類型的同步塊時,它們是否可以由不同的線程或監聽器同時調用?

在沒有看到相關代碼的情況下,這是一個難以回答的問題。 例如。 有人可能正在調用Insert(...)並將其添加到Map但尚未添加到queue ,當另一個線程調用Delete(...) ,該項將在Map找到並刪除但是queue.remove()因為Insert(...)尚未在另一個線程中完成,所以在隊列中找不到它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM