将 ConcurrentHashMap 传递给另一个 class 的最佳方式?
Best way to pass a ConcurrentHashMap to another class?
我有一个处理程序 class,其中包含其他 class 想要的私有 ConcurrentHashMap,但我不确定将其提供给他们的最佳方式。
我明显的选择是..
- Return 整个 ConcurrentHashMap(下面的示例代码——这对我来说听起来很危险,因为 CHM 一次只能由一个线程使用)
- 每次想要 return 整个事情时都创建一个新的 HashMap。
- 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 做什么。
您有三个选择:
Return 地图原样:
return myStuff;
这会让您的其他 classes 修改实际的 myStuff
地图,每个人都会看到更改。然而,不会有任何并发问题,因为ConcurrentHashMap
实际上支持并发访问(因此得名),并且它以一种非常有效的方式实现。
Return地图副本:
return new HashMap(myStuff);
这 return 是每个调用您的 getStuff()
方法的 class 的全新地图。所以每个调用者都可以使用这张地图,因为没有其他人会看到修改,其他调用者 classes 和你的 StuffHandler
class 都不会看到。请记住,如果地图很大,每次调用 getter 时,它可能会导致昂贵的 到 return 副本。
Return 地图的不可修改 视图:
return Collections.unmodifiableMap(myStuff);
这不是 return 地图的副本。实际上,它不会复制任何内容,而是 return 是您的地图的包装器,它不允许修改。这对调用 getStuff()
的 classes 是透明的。此选项 return 是地图的实时视图,因此不会修改实际的 myStuff
地图(如果尝试对 returned 地图进行修改,UnsupportedOperationException
将被抛出)。尽管如此,如果实际的 myStuff
映射被修改(通过您的 StuffHandler
class 的某种方法),所有其他调用 getStuff()
的 class 将看到此修改.
我有一个处理程序 class,其中包含其他 class 想要的私有 ConcurrentHashMap,但我不确定将其提供给他们的最佳方式。
我明显的选择是..
- Return 整个 ConcurrentHashMap(下面的示例代码——这对我来说听起来很危险,因为 CHM 一次只能由一个线程使用)
- 每次想要 return 整个事情时都创建一个新的 HashMap。
- 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 做什么。
您有三个选择:
Return 地图原样:
return myStuff;
这会让您的其他 classes 修改实际的
myStuff
地图,每个人都会看到更改。然而,不会有任何并发问题,因为ConcurrentHashMap
实际上支持并发访问(因此得名),并且它以一种非常有效的方式实现。Return地图副本:
return new HashMap(myStuff);
这 return 是每个调用您的
getStuff()
方法的 class 的全新地图。所以每个调用者都可以使用这张地图,因为没有其他人会看到修改,其他调用者 classes 和你的StuffHandler
class 都不会看到。请记住,如果地图很大,每次调用 getter 时,它可能会导致昂贵的 到 return 副本。Return 地图的不可修改 视图:
return Collections.unmodifiableMap(myStuff);
这不是 return 地图的副本。实际上,它不会复制任何内容,而是 return 是您的地图的包装器,它不允许修改。这对调用
getStuff()
的 classes 是透明的。此选项 return 是地图的实时视图,因此不会修改实际的myStuff
地图(如果尝试对 returned 地图进行修改,UnsupportedOperationException
将被抛出)。尽管如此,如果实际的myStuff
映射被修改(通过您的StuffHandler
class 的某种方法),所有其他调用getStuff()
的 class 将看到此修改.