我有一个处理程序类,其中包含其他类所需的私有ConcurrentHashMap,但我不确定将它提供给它们的最佳方法。
我明显的选择是..
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; } }
答案 0 :(得分:2)
鉴于CHM一次只能由一个线程使用
这根本不准确。 &#34;并发&#34; ConcurrentHashMap
的一部分意味着&#34;对多个线程并发使用是安全的。&#34;正如javadoc注意到:
支持检索完全并发和高的哈希表 预期的更新并发性。
如果您不希望您的消费者能够改变Map
,您可以创建副本(然后甚至看不到更新)或用unmodifiableMap换行(可以看到更新)。
答案 1 :(得分:2)
没有将 ConcurrentHashMap
传递给另一个类的最佳方法。这一切都取决于你的用例,即你希望你的课程做什么。
您有三种选择:
按原样返回地图:
return myStuff;
这会让您的其他课程修改实际的myStuff
地图,每个人都会看到更改。但是,不存在任何并发问题,因为ConcurrentHashMap
实际上支持并发访问(因此它的名称),并且它以非常有效的方式完成。
返回地图的副本:
return new HashMap(myStuff);
这将为每个调用getStuff()
方法的类返回一个全新的地图。因此,每个调用者都可以使用此映射,因为没有其他人会看到修改,无论是其他调用者类还是StuffHandler
类。请记住,如果地图很大,每次调用getter时都可能会导致昂贵的返回副本。
返回地图的不可修改的视图:
return Collections.unmodifiableMap(myStuff);
这不会返回地图的副本。实际上,它不会复制任何内容,而是返回地图的包装,而不允许修改。这对于调用getStuff()
的类是透明的。此选项返回地图的实时视图,因此不会修改实际的myStuff
地图(如果尝试修改返回的地图,则会抛出UnsupportedOperationException
)。尽管如此,如果修改了实际的myStuff
地图(通过StuffHandler
类的某种方法),则调用getStuff()
的每个其他类都会看到此修改。
答案 2 :(得分:1)
如果您希望获取地图的每个对象获得相同的数据,并且其他类可以看到一个类所做的更改,则需要直接返回“myStuff”。
如果您希望获取地图的每个对象都拥有自己的副本,并且如果您不希望另一个对象看到某个对象所做的更改,则返回“myStuff”的副本。