这是一个我也在寻找答案的问题。 < code> puperfutifAbsent 的方法实际上并不能解决额外对象创建问题, 它只是确保其中的一个对象不会取代另一个对象。 但是线条之间的种族条件可能导致多个对象即时化。 我可以找到三个解决这个问题的解决方案( 我会遵循这个优先顺序 ):
1 - 如果您在 Java 8 上, 实现此目标的最佳方法可能是新的 < code> compututeIfAbsent 方法, 即 < code> ConcurrentMap 。 您只需要给它一个将同步执行的计算函数( 至少对于 < Code> ConventHashMap 执行来说是这样 )。 例如 :
private final ConcurrentMap<String, List<String>> entries =
new ConcurrentHashMap<String, List<String>>();
public void method1(String key, String value) {
entries.computeIfAbsent(key, s -> new ArrayList<String>())
.add(value);
}
这是来自Convol-HashMap.computeif-Absense
的javadoc:
If the specified key is not already associated with a value, attempts
to compute its value using the given mapping function and enters it
into this map unless null. The entire method invocation is performed
atomically, so the function is applied at most once per key. Some
attempted update operations on this map by other threads may be
blocked while computation is in progress, so the computation should be
short and simple, and must not attempt to update any other mappings of
this map.
2- 如果无法使用 Java 8, 您可以使用 Guava
s LoadingCache
, 这是线索安全的。 您可以对它定义一个负载函数( 就像上面的 compute
函数), 您可以确定它会同步被命名 。 例如 :
private final LoadingCache<String, List<String>> entries = CacheBuilder.newBuilder()
.build(new CacheLoader<String, List<String>>() {
@Override
public List<String> load(String s) throws Exception {
return new ArrayList<String>();
}
});
public void method2(String key, String value) {
entries.getUnchecked(key).add(value);
}
3 - 如果您也不能使用瓜瓦, 您可以手动同步, 并进行双重检查的锁定。 例如 :
private final ConcurrentMap<String, List<String>> entries =
new ConcurrentHashMap<String, List<String>>();
public void method3(String key, String value) {
List<String> existing = entries.get(key);
if (existing != null) {
existing.add(value);
} else {
synchronized (entries) {
List<String> existingSynchronized = entries.get(key);
if (existingSynchronized != null) {
existingSynchronized.add(value);
} else {
List<String> newList = new ArrayList<>();
newList.add(value);
entries.put(key, newList);
}
}
}
}
我举例说明了所有这三种方法以及非同步方法的实施情况,这些方法导致产生额外的物体: