我目前正在使用ConcurrentHashMap,根据我使用org.apache.commons.lang.RandomStringUtils#randomAlphanumeric
生成的唯一ID存储一些文件。
我目前的做法是:
private ConcurrentHashMap <String, CustomFile> fileIdMap =
new ConcurrentHashMap <String, SwitchConfigurationFile>();
public void importFile () {
CustomFile file = new CustomFile (generateFileID(), param1, param2, param3, param4);
fileIdMap.put (file.getID(), file);
}
private String generateFileID () {
String generatedValue = RandomStringUtils.randomAlphanumeric(5);
while (fileIdMap.containsKey(generatedValue)) {
generatedValue = RandomStringUtils.randomAlphanumeric(5);
}
//I was thinking here to put the generated value into the Map
//but at this moment I don't have the CustomFile instance
//and null values are not allowed
//maybe:
//fileIdMap.put (generatedValue, new CustomFile());
return generatedValue;
}
我在想:如果fileIdMap.containsKey(generatedValue)
返回false并且在我将其添加到地图之前另一个线程出现并添加相同的键,我会在地图中有一个CustomFile而不是两个。我知道机会非常小,但我想考虑到这一点。
那么,在这种情况下最好的方法是什么?如何确保每个文件都有唯一的ID?
答案 0 :(得分:2)
您可以使用putIfAbsent(K key, V value):
private String generateFileID () {
CustomFile file = new CustomFile();
String generatedValue = RandomStringUtils.randomAlphanumeric(5);
while (fileIdMap.putIfAbsent(generatedValue, file) != null) {
generatedValue = RandomStringUtils.randomAlphanumeric(5);
}
return generatedValue;
}
ConcurrentHashMap
中此方法的实现正确synchronized
,以避免出现并发问题。
答案 1 :(得分:0)
你可以使用#putIfAbsent()
,它会以原子方式将项目放在地图中,否则返回null,这样你就可以放入你的while循环而不是null。
您需要稍微重构一下代码,因为您还没有CustomFile
实例。
你可以做的一件事就是首先放置一个虚拟项目,然后在创建它之后用真实对象替换它,但如果其他线程同时读取该对象,这可能会导致另一个同步问题。