【问题标题】:Concurrent access to Java HashMap object并发访问 Java HashMap 对象
【发布时间】:2019-01-20 09:37:55
【问题描述】:

我正在构建一个 Java REST 应用程序,我在其中使用 HashMap 来存储一些数据。

由于它有一个服务器,它可以同时处理多个访问 HashMap 的请求。发出的所有请求都会检查 Map 是否具有预定义的值(该值取决于请求正文),如果没有,则将该值添加到 Map 并返回它。如果 Map 已经具有该值,它只会返回 Map 上的值。

为了拥有一个工作可靠的系统,我应该考虑什么?我将在 Map 上进行多次读取和一些写入(主要是在应用程序启动时,因为 Map 将为空)。

tl;dr

  • 将处理多个同时请求的 Java 服务器。
  • 每个请求都将至少发出一个Map.containsKey(someKey) 并最终发出一个Map.get(someKey)
  • 有些请求会发出Map.put(someKey, someValue)

我应该使用某种并发数据结构吗?

为了争论,我知道使用内存解决方案并不可靠。这不是用于生产用途,它只是学术用途。

【问题讨论】:

  • “为了拥有一个工作可靠的系统,我应该考虑什么”从可靠性的角度来看,任何类型的内存存储都是一个糟糕的选择。
  • docs.oracle.com/javase/8/docs/api/java/util/concurrent/… 但是地图可能会从它读取“containsKey”的点更改为“get”的点。在这种情况下,锁定可能是解决方案,但这会影响性能。
  • 我认为您需要详细说明您的要求。如果您只需要一个线程安全的解决方案(竞争条件/线程可见性),那么ConcurrentHashMap 应该可以工作。但是如果第一个请求也是映射整个生命周期中的最终值很重要,那么它可能还不够(如果值不同),因为两个线程最终可能会从containsKey 得到错误,然后都调用put。在这种情况下,您需要 containsKeyput 成为原子操作。
  • @Jeppe:原子操作由ConcurrentMap#computeIfAbsent提供
  • @Thilo 会不会 ConcurrentMap#putIfAbsent 是一个更好的选择呢?这样我就不需要编写代码插入到地图中,因为方法本身会这样做

标签: java dictionary concurrency concurrenthashmap


【解决方案1】:

首先假设我们使用的是ConcurrentHashMap,它是HashMap 的一个版本,在并行访问时具有更可预测和更直观的内存一致性效果。

鉴于此,最大的考虑是尽可能使单个键上的所有操作都原子化,或者至少不会被另一个想要对该键执行其他操作的线程中断。如果您使用的是 Java 8 或更高版本,则使用 ConcurrentHashMapcomputeIfAbsent 方法实现将在计算和存储新值时阻止其他线程。

...作为应用程序开发人员,这正是您想要的:使用经过专家编写、审查、测试和使用的库,以了解您正在编写的语言和环境的并发效果应用。

【讨论】:

    【解决方案2】:

    如果你想把它保存在内存中,你需要使用 ConcurrentHashMap。

    但是如果您重新启动应用程序并丢失内存数据会发生什么?

    【讨论】:

    • 这是一种学术练习,我知道最好的方法是将其保存在数据库中
    • 明白。比使用 ConcurrentHashMap。
    猜你喜欢
    • 1970-01-01
    • 2020-09-09
    • 1970-01-01
    • 2018-07-24
    • 1970-01-01
    • 2011-10-17
    • 1970-01-01
    • 2014-10-01
    • 1970-01-01
    相关资源
    最近更新 更多