Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 唯一数生成算法_Java_Algorithm_Uniqueidentifier - Fatal编程技术网

Java 唯一数生成算法

Java 唯一数生成算法,java,algorithm,uniqueidentifier,Java,Algorithm,Uniqueidentifier,我需要为满足以下要求的Java应用程序生成唯一的编号- 9位十六进制 每天大约生成60万个数字 数字必须在至少7天内保持唯一性;如果它们在7天内重复出现,则不成问题 在峰值负载期间,大约15秒钟内,每秒需要生成800个唯一的数字 不成功的解决方案- public static String getUniqueId() { String uniqueTime = Long.toHexString(System.nanoTime()); String uniq

我需要为满足以下要求的Java应用程序生成唯一的编号-

  • 9位十六进制
  • 每天大约生成60万个数字
  • 数字必须在至少7天内保持唯一性;如果它们在7天内重复出现,则不成问题
  • 在峰值负载期间,大约15秒钟内,每秒需要生成800个唯一的数字
  • 不成功的解决方案-

        public static String getUniqueId() {
            String uniqueTime = Long.toHexString(System.nanoTime());
            String uniqueId = uniqueTime.substring(uniqueTime.length() - 9);
    
            return uniqueId;
        }
    
    使用nanoTime生成12位十六进制数。我截断了左边的3个字符。nanoTime有助于处理峰值负载

    我认为这是不正确的,可能会导致重复


    有谁能提供一个好的快速算法吗?

    如果只使用一个线程生成数字:

    long nextId = counter % MAX_VALUE;
    counter++;
    return convertToHex(nextId);
    
    如果有多个线程:

    long nextId = atomicLongCounter.getAndIncrement() % MAX_VALUE;
    return convertToHex(nextId);
    

    注:根据@Gumbo的计算,需要313年才能达到最大值,因此您甚至可以删除模。

    如果只使用一个线程生成数字:

    long nextId = counter % MAX_VALUE;
    counter++;
    return convertToHex(nextId);
    
    如果有多个线程:

    long nextId = atomicLongCounter.getAndIncrement() % MAX_VALUE;
    return convertToHex(nextId);
    

    注:根据@Gumbo的计算,需要313年才能达到最大值,因此您甚至可以删除模。

    -另一种并发生成数字的可能性

    最多可以有10个独立的线程/进程/机器生成保证不会冲突的编号

    只需使用顺序计数器生成一个整数

    start one of them at 0, use increments of 10
    start the next at 1, increments of 10
    start the next at 2, increments of 10
    
    即使上述其中一个最终达到满负荷,它也可以持续7天而不会溢出9位数字,因为在9位数字之前的序列中大约有1亿位数字是不够的,而且每天只能产生1 mil

    这里的好东西是线程/进程/机器


    顺便说一句,你可以直接以16为基数来做这件事,只需使用16而不是10的增量。或基数5,增量5等

    -同时生成数字的另一种可能性

    最多可以有10个独立的线程/进程/机器生成保证不会冲突的编号

    只需使用顺序计数器生成一个整数

    start one of them at 0, use increments of 10
    start the next at 1, increments of 10
    start the next at 2, increments of 10
    
    即使上述其中一个最终达到满负荷,它也可以持续7天而不会溢出9位数字,因为在9位数字之前的序列中大约有1亿位数字是不够的,而且每天只能产生1 mil

    这里的好东西是线程/进程/机器


    顺便说一句,你可以直接以16为基数来做这件事,只需使用16而不是10的增量。或基数5,增量5等

    如果你不需要这些数字“看起来随机”,那么你可以像其他人建议的那样使用计数器

    我猜你寻找复杂事物的原因是因为你想让数字“看起来随机”。在这种情况下,您可以执行以下操作:

    • 使用SecureRandom实例分配您的号码
    • 在内存中保留一个映射到分配时间的“当前已分配”数字的映射图(我认为在ConcurrentHashMap中存储此数据的600K数字的顺序是几十兆的数据,因此按照今天的标准这不是什么大问题)
    • 每次需要分配一个新数字时,只需通过SecureRandom实例生成9个随机十六进制数字(要求它用5个随机字节填充一个数组,然后丢弃其中的4个字节,即可获得9个十六进制数字的随机数据)
    • 检查您的新号码是否已在分配号码图中。如果是这样的话,只需循环生成一个新的数字,直到得到一个唯一的数字——实际上,对于您提到的数量,这种情况每周只会发生100次左右,因此不会对性能产生影响,尽管您确实需要对此进行说明
    • 定期扫描已分配号码的地图,清除已分配超过7天的号码,以便重新使用

    对于实际应用程序,您还需要考虑持久性:每次分配一个数字时,您都需要在将其返回到客户端之前将其持久化到数据库中,以便在服务器崩溃时恢复状态。类似地,清除操作将在从内存映射中删除之前从数据库中删除分配。

    如果您不需要这些数字“看起来随机”,那么您可以按照其他人的建议使用计数器

    我猜你寻找复杂事物的原因是因为你想让数字“看起来随机”。在这种情况下,您可以执行以下操作:

    • 使用SecureRandom实例分配您的号码
    • 在内存中保留一个映射到分配时间的“当前已分配”数字的映射图(我认为在ConcurrentHashMap中存储此数据的600K数字的顺序是几十兆的数据,因此按照今天的标准这不是什么大问题)
    • 每次需要分配一个新数字时,只需通过SecureRandom实例生成9个随机十六进制数字(要求它用5个随机字节填充一个数组,然后丢弃其中的4个字节,即可获得9个十六进制数字的随机数据)
    • 检查您的新号码是否已在分配号码图中。如果是这样的话,只需循环生成一个新的数字,直到得到一个唯一的数字——实际上,对于您提到的数量,这种情况每周只会发生100次左右,因此不会对性能产生影响,尽管您确实需要对此进行说明
    • 定期扫描已分配号码的地图,清除已分配超过7天的号码,以便重新使用
    对于实际应用程序,您还需要考虑持久性:每次分配一个数字时,您都需要在将其返回到客户端之前将其持久化到数据库中,以便在服务器崩溃时恢复状态。类似地,清除操作将在从内存映射中删除分配之前从数据库中删除分配。

    只使用一个?它们在这种情况下非常有用

    就用一把椅子怎么样?