【问题标题】:Concurrent Map with fixed size固定大小的并发映射
【发布时间】:2015-01-01 17:12:55
【问题描述】:

我需要一张符合以下要求的地图:

  1. 它应该是高度并发的。 put()get()remove() 方法可以被多个线程同时调用。

  2. 它应该是固定大小的。如果HashMap 的大小达到最大值(例如 10000),则不应允许向映射添加新条目。它不能是 LRU 缓存,其中最旧的条目在达到最大大小时会被删除。

ConcurrentHashMap 可能满足#1。但是,不确定如何在ConcurrentHashMap 之上实现#2 而不会影响并发性(添加一个自定义put() 方法,仅当大小小于最大大小时才会添加到地图中,需要“同步” . 这将破坏使用并发HashMap) 的目的。

请告诉我你的想法。

【问题讨论】:

  • 放之前检查尺寸?
  • 在 concurrenthashmap 中报告的大小不准确。也许使用带有计数信号量的concurrenthashmap?
  • “不确定如何在 ConcurrentHashMap 之上实现 #2 而不会影响并发”...我不明白为什么会出现问题。您创建一个包装器,在并发映射之上引入计数器。为了同步对计数器的访问,您使用自己的同步原语(例如,ReentrantLock)来最小化额外的开销并将其与并发映射同步分开。那么一切都应该正常工作
  • @NathanHughes 我认为您应该写一个新答案并解决问题。 +1
  • 这个最大值必须有多严格?如果某些竞争条件是可以容忍的,我认为只需对所有 mutator 方法添加检查即可(尽管注意 size() 不是恒定时间)。如果你真的需要一个硬上限,你将很难在不严重损害并发性的情况下强制执行——即使信号量的想法也需要同步。您能否提供更多关于您的用例的详细信息,以及为什么您认为固定大小的并发集合是正确的解决方案?这对我来说听起来像是一个 XY 问题。

标签: java multithreading concurrency java.util.concurrent concurrenthashmap


【解决方案1】:

为了解决我对有界并发哈希映射的要求:在使用映射之前检查映射的大小。

【讨论】:

    【解决方案2】:

    如何始终保持Hashmap的大小以保证插入的元素总数?您可以使用AtomicInteger,这样您就不必同步/锁定常规 int 并牺牲使用 ConcurrentHashMap 的好处。

    【讨论】:

      【解决方案3】:

      您可以实现一个委托给 ConcurrentHashMap 的映射,使用计数信号量来限制映射中的项目数。 Semaphore 类使用原子更新的 int 来跟踪许可,因此不会产生太多额外开销。

      【讨论】:

      • put之前使用SemaphoretryAcquire,在remove之后使用release,因为你不想阻止。
      【解决方案4】:

      如果使用 ConcurrentHashMap,这是显而易见的选择,那么使用 concurrencyLevel 输入到构造函数以增加带宽 - 这会将地图分割成多个区域以避免放置冲突。

      【讨论】:

      • 更改 concurrencyLevel 并不能解决他的固定大小 ConcurrentMap 的问题。
      • 同意。这不会解决固定大小的 ConcurrentMap 问题。
      • 我也同意,但它会提高并发性,这是他关心的另一个问题。值得注意。
      【解决方案5】:

      您可以自己完成所有这些工作,仅 java SE 工具库就可以满足您的需求,但我强烈建议您使用更简单且更具可扩展性的方法,因为您自己完成所有这些工作将是重新发明轮子。在内存数据网格中尝试其中一种:

      例如,在 ehcache 中,您可以通过类似的配置来实现您想要的:

      <cache 
       name="myCache"
       maxElementsInMemory="10000"
       eternal="true"
       overflowToDisk="false" />
      

      【讨论】:

      • 主要的缺点是这会慢很多数量级。
      • 我同意它会,但是在选择要优化的内容时应该有选择性。我使用的一些分布式哈希映射在不同区域保存了数百万个数据,其相关服务在可接受的时间范围内响应。考虑到所有这些,10000 是一个非常非常小的数字。
      • 我还没有检查细节,但是,我不需要分布式缓存。我可以接受满足上述要求的简单哈希映射。那么,这是否意味着带有信号量的 ConcurrentHashMap 更有意义?
      • 您不必以分布式方式使用它,但如果您需要它能够成为一个,那就太好了。想象一下你突然决定需要 LRU 的场景,用一行配置打开它不是很好吗?我的观点是关键值数据库概念,无论是作为数据网格还是缓存,社区已经在研究。为什么要创建自己的简单实现,因为您可以使用社区付出巨大努力创建和支持的实现。
      • 如果您需要超出您之前已经创建的范围的东西,您可以随时贡献项目并帮助我们所有人。
      猜你喜欢
      • 2019-02-05
      • 2016-01-25
      • 2020-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-28
      • 2011-02-28
      • 1970-01-01
      相关资源
      最近更新 更多