我需要在Java中生成一个唯一的10位ID。这些是此ID的限制:
只有数字
最多10位
每秒最多可以创建10个不同的ID
必须是唯一的(即使应用程序重新启动)
无法在数据库中保存数字
尽可能快,不要给系统增加太多的间隔
到目前为止,我找到的最佳解决方案是:
private static int inc = 0;
private static long getId(){
long id = Long.parseLong(String.valueOf(System.currentTimeMillis())
.substring(1,10)
.concat(String.valueOf(inc)));
inc = (inc+1)%10;
return id;
}
此解决方案存在以下问题:
如果出于任何原因,需要每秒钟创建超过10个ID,那么这个解决方案将无法工作。
在大约32年内,这个ID可以重复(这可能是可以接受的)
有其他创建此ID的解决方案吗?
还有什么我没想到的问题吗?
谢谢你的帮助,
应用程序的多个实例可以同时运行吗?
目前只有一个实例正在运行,但在将来可能是可能的。我们还有一个secondary实例,以防primary崩溃,但只有一个实例(primary或secondary)会同时运行。
正如下面的一些答案所指出的,我的实现将在多实例或多线程环境中失败,因此我们假设一个具有单个线程的实例将运行。
如果不引入某种形式的通信(如数据库、文件或Web服务),就不可能保证跨实例的唯一性。
这是对您的一个小增强,但应该是弹性的。
private static final long LIMIT = 10000000000L;
private static long last = 0;
public static long getID() {
// 10 digits.
long id = System.currentTimeMillis() % LIMIT;
if ( id <= last ) {
id = (last + 1) % LIMIT;
}
return last = id;
}
事实上,它应该以相对较短的周期速率管理高达每秒1000次。为了延长循环速率(但缩短分辨率),可以使用(System.currentTimeMillis() / 10) % 10000000000L或(System.currentTimeMillis() / 100) % 10000000000L。
让它线程安全也是一个好主意。
如果必须在同一秒内创建更多THA 10 ID,那么使用(system.currentTimeMillis()/100)实际上可以解决问题,因为这永远不会是连续的。谢谢,;)
请记住,System.currentTimeMillis()的分辨率最低。我发现它在MS系统上运行大约15毫秒,所以/100可能不像您想象的那样平滑,尽管这个算法可以为您解决这个问题。
我正在考虑使用/100,但我看到了一个问题:这个简单的例子失败了:时间:1376479263900 ID:时间:1376479263950 ID:时间:1376479264000 ID:时间:1376479264050 ID:(重复)
@magodiez-用/100你应该得到@t=1376479263900 id=13764792639,@t=1376479263950 id=3764792640,@t=1376479264000 id=3764792641,@t=1376479264050 id=3764792642…直到你退后足够长的时间来赶上。它永远不会返回一个ID<=最后一个ID,除非您绕过10位的限制或重新启动。注意,我在第一篇文章之后对算法做了一些调整,所以得到最新的结果,你会发现它是可以的。
如果在second 1999999999中创建了多个ID,这可能会有问题,但直到2033年(足够好)仍然没有问题,谢谢,:)
这可能是一个疯狂的想法,但这是一个想法:)。
首先生成uuid,并使用java.util.UUID.randomUUID().toString()。
第二次将生成的字符串转换为字节数组(byte[])
然后将其转换为长缓冲区:java.nio.ByteBuffer.wrap( byte
digest[] ).asLongBuffer().get()。
截断到10位
对于这种方法tho的唯一性不确定,我知道您可以依赖于uuid的唯一性,但还没有检查它们如何被转换和截断为10位长的数字。
例子取自哈维拉赫,也许还有更多。
编辑:当你被限制到10位数字时,简单的随机生成器就足够了,看看S/JAVION/SO:0:<
UUID不保证是唯一的。虽然获得两个相同的UUID的概率很小。
没错,但正如我所写的"你可以依靠它们的独特性",而不是它们的独特性:)
private static atomicreference currentTime=new atomicreference<>(system.currentTimeMillis());
public static Long nextId() {
return currentTime.accumulateAndGet(System.currentTimeMillis(), (prev, next) -> next > prev ? next : prev + 1) % 10000000000L;
}
号
请将您的答案编辑为正确的代码格式。另外,添加一些解释
什么意味着它必须是独一无二的?甚至在当前运行的更多实例中?它会破坏您的实现。
如果它必须在整个宇宙中是唯一的,那么最好的解决方案是使用UUID,因为它是数学上证明的标识符生成器,因为它为每个宇宙生成唯一的值。不太准确的数字会带来碰撞。
当只有一个并发实例时,可以以毫秒为单位计算当前时间,并使用递增法解决10毫秒的问题。如果在数字中牺牲适当数量的最后一个位置,您可以在一毫秒内得到许多数字。我不想定义精度-我的意思是你每秒钟需要多少唯一的数字。您将使用这种方法解决这个问题,而不需要任何持久性。