将 ConcurrentHashMap 传递给另一个 class 的最佳方式?

Best way to pass a ConcurrentHashMap to another class?

我有一个处理程序 class,其中包含其他 class 想要的私有 ConcurrentHashMap,但我不确定将其提供给他们的最佳方式。

我明显的选择是..

  1. Return 整个 ConcurrentHashMap(下面的示例代码——这对我来说听起来很危险,因为 CHM 一次只能由一个线程使用)
  2. 每次想要 return 整个事情时都创建一个新的 HashMap。
  3. Return 一个迭代器...但我讨厌迭代器!它只会是键或值。
public class StuffHandler {
    private StuffHandler(){}
    public static synchronized StuffHandler getInstance() {
        return INSTANCE;
    }
    private final static ConcurrentHashMap<String, Stuff> myStuff = new ConcurrentHashMap<>();
    public static ConcurrentHashMap<String, Stuff> getStuff() {
        return myStuff;
    }
}

given that CHMs are meant to be used by only one thread at a time

这根本不准确。 ConcurrentHashMap 的 "Concurrent" 部分表示 "safe for concurrent use by multiple threads." 正如 javadoc 注释:

A hash table supporting full concurrency of retrievals and high expected concurrency for updates.

如果您不希望您的消费者能够改变 Map,您可以创建一个副本(然后甚至看不到更新)或用 unmodifiableMap 包装(可以看到更新)。

如果您希望获取地图的每个对象都获得相同的数据,并且一个 class 所做的更改对另一个 class 可见,您希望 return 'myStuff'直接

如果您希望获取地图的每个对象都有自己的副本,并且不希望一个对象所做的更改被另一个对象看到,return 'myStuff'。

没有将一个 ConcurrentHashMap 传递给另一个class的最佳方法。这完全取决于您的用例,即您希望 classes 做什么。

您有三个选择:

  1. Return 地图原样:

    return myStuff;
    

    这会让您的其他 classes 修改实际的 myStuff 地图,每个人都会看到更改。然而,不会有任何并发​​问题,因为ConcurrentHashMap实际上支持并发访问(因此得名),并且它以一种非常有效的方式实现。

  2. Return地图副本:

    return new HashMap(myStuff);
    

    这 return 是每个调用您的 getStuff() 方法的 class 的全新地图。所以每个调用者都可以使用这张地图,因为没有其他人会看到修改,其他调用者 classes 和你的 StuffHandler class 都不会看到。请记住,如果地图很大,每次调用 getter 时,它可能会导致昂贵的 到 return 副本。

  3. Return 地图的不可修改 视图:

    return Collections.unmodifiableMap(myStuff);
    

    这不是 return 地图的副本。实际上,它不会复制任何内容,而是 return 是您的地图的包装器,它不允许修改。这对调用 getStuff() 的 classes 是透明的。此选项 return 是地图的实时视图,因此不会修改实际的 myStuff 地图(如果尝试对 returned 地图进行修改,UnsupportedOperationException将被抛出)。尽管如此,如果实际的 myStuff 映射被修改(通过您的 StuffHandler class 的某种方法),所有其他调用 getStuff() 的 class 将看到此修改.