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