简体   繁体   English

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

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

I'm currently using a ConcurrentHashMap in which I store some files based on a unique id that I generate using org.apache.commons.lang.RandomStringUtils#randomAlphanumeric . 我当前正在使用ConcurrentHashMap,其中基于我使用org.apache.commons.lang.RandomStringUtils#randomAlphanumeric生成的唯一ID存储一些文件。

My current approach is this: 我当前的方法是这样的:

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;
}

I was thinking: What if fileIdMap.containsKey(generatedValue) returns false and before I add it to the map another thread comes and adds the same key, I will have one CustomFile in the map instead of two. 我在想:如果fileIdMap.containsKey(generatedValue)返回false,并且在我将其添加到地图之前,另一个线程来添加相同的密钥,我将在地图中拥有一个CustomFile而不是两个。 I know the chances are very small, but I want to take this into consideration. 我知道机会很小,但是我要考虑到这一点。

So, what is the best approach in this situation and how can I ensure that I also have a unique id for each file? 那么,在这种情况下最好的方法是什么,如何确保每个文件也具有唯一的ID?

You can use putIfAbsent(K key, V value) : 您可以使用putIfAbsent(K键,V值)

private String generateFileID () {
   CustomFile file = new CustomFile();
   String generatedValue = RandomStringUtils.randomAlphanumeric(5);
   while (fileIdMap.putIfAbsent(generatedValue, file) != null) {
       generatedValue = RandomStringUtils.randomAlphanumeric(5);
   }
   return generatedValue;
}

The implementation of this method in ConcurrentHashMap is correctly synchronized to avoid concurrence problems. ConcurrentHashMap中此方法的实现已正确synchronized以避免并发问题。

You can use #putIfAbsent() , which will atomically place the item in the map or return null otherwise, so you could put in your while loop while not null. 您可以使用#putIfAbsent() ,该方法会自动将该项放置在地图中,否则将返回null,因此您可以在不为null的情况下放入while循环。
You will need to refactor your code a bit, since you don't yet have the CustomFile instance. 由于您还没有CustomFile实例,因此需要重构代码。
One thing you could do is place a dummy item in first, then replace it with your real object once it is created, but this might cause another synchronization issues if other threads read that object in the mean time. 您可以做的一件事是首先放置一个虚拟项目,然后在创建真实对象后将其替换,但是如果其他线程同时读取该对象,则这可能会引起另一个同步问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM