实现并发 LinkedHashMap

发布于 2024-08-29 19:49:15 字数 458 浏览 2 评论 0原文

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

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

如果我使用 ConcurrentSkipListMap 是否有任何方法可以实现比较器来按顺序存储,如存储在链接列表或队列中。

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

编辑:

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

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

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

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

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

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

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

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.

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

兮子 2024-09-05 19:49:16

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

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.

傾城如夢未必闌珊 2024-09-05 19:49:16

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

  1. 编写仅允许插入顺序的 LHM。
  2. 切换到 ConcurrentHashMap 作为哈希表。
  3. 使用锁保护#put() / #putIfAbsent() / #remove()
  4. 使“下一个”字段变得不稳定。

在迭代时,不需要锁定,因为您可以安全地遵循“下一个”字段。只需在 #get() 上委托给 CHM 即可实现无锁读取。

A LinkedHashMap has 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.

  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.

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().

笑梦风尘 2024-09-05 19:49:16

使用 <代码>Collections#synchronizedMap()

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

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

Use Collections#synchronizedMap().

As per my belief, if I use Collections.synchronizedMap(), I would have to use synchronized blocks for 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.

怂人 2024-09-05 19:49:16

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

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

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

I have switched to MapMaker from Google Guava. You can look at CacheBuilder too.

ㄖ落Θ余辉 2024-09-05 19:49:16

嗯,简单的答案是使用您的 Comparator 运行的单调递增密钥提供程序。想想AtomicInteger,每次插入时,都会创建一个用于比较的新键。如果您汇集真实密钥,则可以创建 OrderedKey 的内部映射。

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) 方法来计算大小(除非您允许删除,在这种情况下,也对这些进行计数,因此您只需从“中减去”所有成功删除”即可所有成功添加”,其中成功意味着实际创建或删除了条目)。

Um, simple answer would be to use a monotonically increasing key provider that your Comparator operates 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>.

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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文