将ConcurrentHashMap传递给另一个类的最佳方法?

时间:2015-02-22 00:13:51

标签: java thread-safety singleton concurrenthashmap

我有一个处理程序类,其中包含其他类所需的私有ConcurrentHashMap,但我不确定将它提供给它们的最佳方法。

我明显的选择是..

  1. 返回整个ConcurrentHashMap(下面的示例代码 - 这对我来说很危险,因为CHM一次只能由一个线程使用)
  2. 每次想要返回整个内容时创建一个新的HashMap。
  3. 返回一个迭代器......但我讨厌迭代器!它只是键或值。
  4. 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;
        }
    }
    

3 个答案:

答案 0 :(得分:2)

  

鉴于CHM一次只能由一个线程使用

这根本不准确。 &#34;并发&#34; ConcurrentHashMap的一部分意味着&#34;对多个线程并发使用是安全的。&#34;正如javadoc注意到:

  

支持检索完全并发和高的哈希表   预期的更新并发性。

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

答案 1 :(得分:2)

没有 ConcurrentHashMap 传递给另一个类的最佳方法。这一切都取决于你的用例,即你希望你的课程做什么。

您有三种选择:

  1. 按原样返回地图:

    return myStuff;
    

    这会让您的其他课程修改实际的myStuff地图,每个人都会看到更改。但是,不存在任何并发问题,因为ConcurrentHashMap实际上支持并发访问(因此它的名称),并且它以非常有效的方式完成。

  2. 返回地图的副本:

    return new HashMap(myStuff);
    

    这将为每个调用getStuff()方法的类返回一个全新的地图。因此,每个调用者都可以使用此映射,因为没有其他人会看到修改,无论是其他调用者类还是StuffHandler类。请记住,如果地图很大,每次调用getter时都可能会导致昂贵的返回副本。

  3. 返回地图的不可修改的视图

    return Collections.unmodifiableMap(myStuff);
    

    这不会返回地图的副本。实际上,它不会复制任何内容,而是返回地图的包装,而不允许修改。这对于调用getStuff()的类是透明的。此选项返回地图的实时视图,因此不会修改实际的myStuff地图(如果尝试修改返回的地图,则会抛出UnsupportedOperationException)。尽管如此,如果修改了实际的myStuff地图(通过StuffHandler类的某种方法),则调用getStuff()的每个其他类都会看到此修改。

答案 2 :(得分:1)

如果您希望获取地图的每个对象获得相同的数据,并且其他类可以看到一个类所做的更改,则需要直接返回“myStuff”。

如果您希望获取地图的每个对象都拥有自己的副本,并且如果您不希望另一个对象看到某个对象所做的更改,则返回“myStuff”的副本。