如何正确生成唯一 ID 并将其存储在 ConcurrentHashMap 中

How to properly generate a unique id and store it in a ConcurrentHashMap

我目前正在使用 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) returns false 并且在我将它添加到地图之前另一个线程出现并添加相同的键,我将在地图中有一个 CustomFile 而不是两个.我知道机会很小,但我想考虑到这一点。

那么,在这种情况下最好的方法是什么?我怎样才能确保每个文件都有一个唯一的 ID?

您可以使用 #putIfAbsent(),它会自动将项目放置在地图中,否则 return null,这样您就可以在不为 null 的情况下放入 while 循环。
您需要稍微重构一下代码,因为您还没有 CustomFile 实例。
您可以做的一件事是先放置一个虚拟项,然后在创建后将其替换为您的真实对象,但是如果其他线程同时读取该对象,这可能会导致另一个同步问题。

您可以使用 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以避免并发问题。