繁体   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