实现并发LinkedHashMap
我正在尝试为multithreading架构创建并发LinkedHashMap。
如果我使用Collections#synchronizedMap()
,我将不得不使用synchronized块进行迭代。 这种实现将导致元素的顺序添加。
如果我使用ConcurrentSkipListMap
有任何方法可以实现Comparator
按顺序存储,如存储在Linked List或队列中。
我想使用java内置而不是第三方软件包。
编辑:
在这个并发的LinkedHashMap
,如果键是名称,我希望按顺序放置键。 即,新值将在开始或结束时附加到,但是顺序地附加。
迭代时, LinkedHashMap
可以添加新条目,也可以删除。 但迭代应该是添加条目的顺序。
我理解通过使用Collections#synchronizedMap()
,必须实现用于迭代的同步块,但是在迭代时地图是可修改的(可以添加/删除条目)。
如果使用synchronizedMap,则不必在外部进行同步,迭代除外。 如果需要保留地图的顺序,则应使用SortedMap。 您可以使用ConcurrentSkipListMap(它是线程安全的)或另一个SortedMap与synchronizedSortedMap结合使用。
LinkedHashMap
具有通过哈希表运行的双向链表。 FIFO仅在写入(插入或移除)时改变链接。 这使得实现版本相当简单。
- 写一个只允许插入顺序的LHM。
- 切换到ConcurrentHashMap作为哈希表。
- 使用锁保护
#put()
/#putIfAbsent()
/#remove()
。 - 使“下一个”字段易变。
在迭代时,不需要锁定,因为您可以安全地遵循“下一个”字段。 只需在#get()
上委托给CHM,读取就可以无锁定。
使用Collections#synchronizedMap()
。
根据我的观点,如果我使用Collections.synchronizedMap(),我将不得不使用synchronized块作为getter / setter。
这不是真的。 您只需要在任何视图(键集,值,条目集)上同步迭代。 另请参阅abovelinked API文档。
到目前为止,我的项目使用了Apache Collections的LRUMap,但它基于SequencedHashMap。 集合提出了ListOrderedMap,但没有一个是线程安全的。
我已从Google Guava切换到MapMaker 。 您也可以查看CacheBuilder 。
嗯,简单的答案是使用Comparator
器操作的单调增加的密钥提供程序。 想想AtomicInteger
,每次插入时,都会创建一个用于比较的新密钥。 如果您汇集真实密钥,则可以创建OrderedKey
的内部映射。
class OrderedKey implements Comparable> { T realKey; int index; OrderedKey(AtomicInteger source, T key) { index = source.getAndIncrement(); realKey = key; } public int compareTo(OrderedKey other) { if (Objects.equals(realKey, other.realKey)) { return 0; } return index - other.index; } }
这样可以避免使用自定义比较器,并为您提供一个很好的O(1)方法来计算大小(除非你允许删除,在这种情况下,也要计算这些,所以你可以从“减去”所有成功的删除)所有成功添加“,成功意味着实际创建或删除了一个条目”。