应使用的java ConcurrentHashMap putIfAbsent或锁定映射
我遇到一种情况,调用方希望根据当前实例(标识符)获取bean的对象。现在,若当前实例中存在bean的对象,那个么不应该再次创建它。因此,有两种方法(我认为)可以做到这一点-
1. Using putIfAbsent of ConcurrentHashMap
beanObject = objectFactory.get(); // this will create new instance every time
// even if not required
beanObject = beanMapForInstance.putIfAbsent(name, beanObject);
return beanObject;
或
2. By Locking the map
beanObject = beanMapForInstance.get(name); // beanMapForInstance is a ConcurrentHashMap
if(beanObject == null){
synchronized (beanMapForInstance) {
beanObject = beanMapForInstance.get(name);
if(beanObject == null){
beanObject = objectFactory.getObject();
beanMapForInstance.put(name, beanObject);
}
}
}
return beanObject;
在第一种方法中,每次都会创建新对象,所以我认为应该首选第二种方法。但findbugs显示了在ConcurrentHashMap上执行同步的第二个选项的问题,那个么应该使用哪一个呢
# 1 楼答案
先检查是否存在,然后再检查是否存在
将在99.99%的时间内工作,在非常罕见的竞争条件下,调用冗余构造函数(除了性能方面的考虑,这显然对您来说不是问题)
# 2 楼答案
在您的情况下,没有选择:您无法锁定
ConcurrentHashMap
。更准确地说,锁定ConcurrentHashMap
并没有像您所期望的那样工作。它不会使您的操作线程安全,因为ConcurrentHashMap
中的线程安全操作不是通过同步对象本身来实现的引自Javadoc of ConcurrentHashMap:
如果您不想创建不必要的值,那么如果您使用的是JDK 8+,那么可以使用
computeIfAbsent
,您可以将实例化延迟到真正需要时