java 实现并发 LinkedHashMap

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2698217/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 22:23:50  来源:igfitidea点击:

Implementing a concurrent LinkedHashMap

javacollectionsconcurrency

提问by Nilesh

I'm trying to create a concurrent LinkedHashMap for a multithreaded architecture.

我正在尝试为多线程架构创建并发 LinkedHashMap。

If I use Collections#synchronizedMap(), I would have to use synchronized blocks for iteration. This implementation would lead to sequential addition of elements.

如果我使用Collections#synchronizedMap(),我将不得不使用同步块进行迭代。这种实现将导致元素的顺序添加。

If I use ConcurrentSkipListMapis there any way to implement a Comparatorto store sequentially, as stored in Linked List or queue.

如果我使用ConcurrentSkipListMap有什么方法可以实现Comparator按顺序存储,如存储在链表或队列中。

I would like to use java's built in instead of third party packages.

我想使用内置的java而不是第三方包。

EDIT:

编辑:

In this concurrent LinkedHashMap, if the keys are the name, I wish to put the keys in sequence of their arrival. i.e. new value would be appended to either at start or end, but sequentially.

在这个并发中LinkedHashMap,如果键是名称,我希望将键按到达顺序排列。即新值将附加到开始或结束时,但顺序。

While iterating, the LinkedHashMapcould be added with new entries, or removed. but the iteration should be the sequence in which the entries were added.

在迭代时,LinkedHashMap可以添加新条目或删除。但迭代应该是添加条目的顺序。

I understand that by using Collections#synchronizedMap(), an synchronized block for iteration would have to be implemented, but would the map be modifiable (entries could be added/removed) while it is being iterated.

我知道通过使用Collections#synchronizedMap(),必须实现用于迭代的同步块,但是映射在迭代时是否可以修改(可以添加/删除条目)。

回答by Matthew Flaschen

If you use synchronizedMap, you don't have to synchronize externally, except for iteration. If you need to preserve the ordering of the map, you should use a SortedMap. You could use ConcurrentSkipListMap, which is thread-safe, or another SortedMap in combination with synchronizedSortedMap.

如果使用了synchronizedMap,除了迭代之外,不需要进行外部同步。如果您需要保留地图的顺序,您应该使用 SortedMap。您可以使用线程安全的 ConcurrentSkipListMap,或与 synchronizedSortedMap 结合使用的另一个 SortedMap。

回答by Ben Manes

A LinkedHashMaphas a doubly linked list running through a hashtable. A FIFO only mutates the links on a write (insertion or removal). This makes implementing a version fairly straightforward.

ALinkedHashMap有一个通过哈希表运行的双向链表。FIFO 仅在写入(插入或移除)时改变链接。这使得实现一个版本相当简单。

  1. Write a LHM with only insertion order allowed.
  2. Switch to a ConcurrentHashMap as the hashtable.
  3. Protect #put()/ #putIfAbsent()/ #remove()with a lock.
  4. Make the "next" field volatile.
  1. 编写一个只允许插入顺序的 LHM。
  2. 切换到 ConcurrentHashMap 作为哈希表。
  3. 保护#put()/ #putIfAbsent()/#remove()用锁。
  4. 使“下一个”字段易变。

On iteration, no lock is needed as you can safely follow the "next" field. Reads can be lock-free by just delegating to the CHM on a #get().

在迭代时,不需要锁定,因为您可以安全地遵循“下一个”字段。读取可以是无锁的,只需将#get().

回答by Yves Martin

Until now, my project used LRUMap from Apache Collections but it is based on SequencedHashMap. Collections proposes ListOrderedMapbut none are thread-safe.

到目前为止,我的项目使用 Apache Collections 中的 LRUMap,但它基于 SequencedHashMap。Collections 建议ListOrderedMap但没有一个是线程安全的。

I have switched to MapMakerfrom Google Guava. You can look at CacheBuildertoo.

我已从Google Guava切换到MapMaker。您也可以查看CacheBuilder

回答by BalusC

Use Collections#synchronizedMap().

使用Collections#synchronizedMap().

As per my belief, if I use Collections.synchronizedMap(), I would have to use synchronized blocks for getter/setter.

根据我的信念,如果我使用 Collections.synchronizedMap(),我将不得不为 getter/setter 使用同步块。

This is not true. You only need to synchronize the iteration on any of the views (keyset, values, entryset). Also see the abovelinked API documentation.

这不是真的。您只需要在任何视图(键集、值、条目集)上同步迭代。另请参阅上面链接的 API 文档。

回答by Ajax

Um, simple answer would be to use a monotonically increasing key provider that your Comparatoroperates on. Think AtomicInteger, and every time you insert, you create a new key to be used for comparisons. If you pool your real key, you can make an internal map of OrderedKey<MyRealKeyType>.

嗯,简单的答案是使用您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;
  }


}

This would obviate the need for a custom comparator, and give you a nice O(1) method to compute size (unless you allow removes, in which case, count those as well, so you can just subtract "all successful removes" from "all successful adds", where successful means an entry was actually created or removed).

这将消除对自定义比较器的需要,并为您提供一个很好的 O(1) 方法来计算大小(除非您允许删除,在这种情况下,也计算这些,因此您可以从“中减去“所有成功删除”所有成功添加”,其中成功意味着实际创建或删除了条目)。