简体   繁体   English

单个数据存储的多个消息侦听器。 高效的设计

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

I have a data store that is written to by multiple message listeners. 我有一个由多个消息监听器写入的数据存储。 Each of these message listeners can also be in the hundreds of individual threads. 这些消息监听器中的每一个也可以在数百个单独的线程中。

The data store is a PriorityBlockingQueue as it needs to order the inserted objects by a timestamp. 数据存储是PriorityBlockingQueue因为它需要按时间戳对插入的对象进行排序。 To make checking of the queue of items efficient rather than looping over the queue a concurrent hashmap is used as a form of index. 为了有效地检查项目队列而不是循环队列, 并发使用并发散列映射作为索引的形式。

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

Question 1 is this a acceptable design or should I just use the single PriorityBlockingQueue. 问题1这是一个可接受的设计,或者我应该只使用单个PriorityBlockingQueue。

Each message listener performs an operation, these listeners are scaled up to multiple threads. 每个消息侦听器都执行一个操作,这些侦听器扩展到多个线程。

Insert Method so it inserts into both. 插入方法,以便插入两者。

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

Update Method 更新方法

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

Delete Method 删除方法

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

Question Two Using these methods is this the most efficient way? 问题二使用这些方法这是最有效的方法吗? They have wrappers around them via another object for error handling. 它们通过另一个对象围绕它们进行包装以进行错误处理。

Question Three Using a concurrent HashMap and BlockingQueue does this mean these operations are thread safe? 问题三使用并发HashMap和BlockingQueue这是否意味着这些操作是线程安全的? I dont need to use a lock object? 我不需要使用锁定对象?

Question Four When these methods are called by multiple threads and listeners without any sort of synchronized block, can they be called at the same time by different threads or listeners? 问题四当多个线程和监听器调用这些方法而没有任何类型的同步块时,它们是否可以由不同的线程或监听器同时调用?

Question 1 is this a acceptable design or should I just use the single PriorityBlockingQueue. 问题1这是一个可接受的设计,或者我应该只使用单个PriorityBlockingQueue。

Certainly you should try to use a single Queue . 当然你应该尝试使用单个Queue Keeping the two collections in sync is going to require a lot more synchronization complexity and worry in your code. 保持两个集合同步将需要更多的同步复杂性并担心代码。

Why do you need the Map ? 你为什么需要Map If it is just to call setNodeId(...) then I would have the processing thread do that itself when it pulls from the Queue . 如果它只是调用setNodeId(...)那么我会让处理线程在从Queue拉出时自己做。

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

Question Two Using these methods is this the most efficient way? 问题二使用这些方法这是最有效的方法吗? They have wrappers around them via another object for error handling. 它们通过另一个对象围绕它们进行包装以进行错误处理。

Sure, that seems fine but, again, you will need to do some synchronization locking otherwise you will suffer from race conditions keeping the 2 collections in sync. 当然,这似乎很好,但是,再次,你需要做一些同步锁定,否则你将遇到竞争条件,使2个集合保持同步。

Question Three Using a concurrent HashMap and BlockingQueue does this mean these operations are thread safe? 问题三使用并发HashMap和BlockingQueue这是否意味着这些操作是线程安全的? I dont need to use a lock object? 我不需要使用锁定对象?

Both of those classes ( ConcurrentHashMap and the BlockingQueue implementations) are thread-safe, yes. 这两个类( ConcurrentHashMapBlockingQueue实现)都是线程安全的,是的。 BUT since there are two of them, you can have race conditions where one collection has been updated but the other one has not. 但是因为有两个,你可以有一个竞争条件,其中一个集合已经更新但另一个没有。 Most likely, you will have to use a lock object to ensure that both collections are properly kept in sync. 最有可能的是,您必须使用锁定对象来确保两个集合都正确保持同步。

Question Four When these methods are called by multiple threads and listeners without any sort of synchronized block, can they be called at the same time by different threads or listeners? 问题四当多个线程和监听器调用这些方法而没有任何类型的同步块时,它们是否可以由不同的线程或监听器同时调用?

That's a tough question to answer without seeing the code in question. 在没有看到相关代码的情况下,这是一个难以回答的问题。 For example. 例如。 someone might be calling Insert(...) and has added it to the Map but not the queue yet, when another thread else calls Delete(...) and the item would get found in the Map and removed but the queue.remove() would not find it in the queue since the Insert(...) has not finished in the other thread. 有人可能正在调用Insert(...)并将其添加到Map但尚未添加到queue ,当另一个线程调用Delete(...) ,该项将在Map找到并删除但是queue.remove()因为Insert(...)尚未在另一个线程中完成,所以在队列中找不到它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM