3 回答
TA贡献1735条经验 获得超5个赞
UUID
128 位 UUID正是为您的目的而发明的:在一台或多台机器上生成标识符,而无需通过中央机构进行协调。
理想情况下,您将使用原始版本 1 UUID,或其在版本 2、3 和 5 中的变体。原始版本采用主机网络接口的 MAC 地址,并将其与当前时刻加上一个小的任意数字相结合,该数字在主机时钟已调整。这种方法消除了对重复项的任何实际关注。
Java 不捆绑生成这些版本的实现。我认为 Java 设计者对泄露地点、时间和 MAC 地址有隐私和安全方面的担忧。
Java 仅针对版本 4 提供了一种生成器实现。在这种类型中,128 位中除了 6 位之外的所有位都是随机生成的。如果使用加密强随机生成器,则此版本足以在大多数常见情况下使用而无需担心冲突。
要知道 122 位是一个非常大的数字范围 (5.316911983139664e+36)。64 位产生的范围为 18,446,744,073,709,552,000(18 quintillion)。剩余的 58 位 (122-64=58) 产生的数字范围为 288,230,376,151,711,740(288 千万亿)。现在将这两个数字相乘得到 122 位的范围:2^122 = ( 18,446,744,073,709,552,000 * 288,230,376,151,711,740 ) 即 5.3十进制。
但是,如果您有权生成 4 以外的 UUID 版本,请接受它。例如,在Postgres等数据库系统中,数据库服务器可以在包括版本 1 在内的各种版本中生成 UUID 编号。或者您可能会找到用于生成此类 UUID 的 Java 库,尽管该库可能不是平台独立的(它可能具有内的本机代码)。
System.nanoTime
明确这与当前日期和时间无关System.nanoTime
。引用 Javadoc:
此方法只能用于测量经过的时间,与系统或挂钟时间的任何其他概念无关。
该System.nanoTime
功能仅返回一个数字,即自某个long
来源以来的纳秒计数,但未指定该来源。
Java 规范中唯一的承诺是源在 JVM 运行期间不会改变。所以你知道这个数字在你的应用程序执行期间不断增加。除非达到a 的限制long
,否则计数器将翻转。如果原点为零,则翻转可能需要 292 年(2^63 纳秒)——但同样,原点未指定。
根据我使用过的特定 Java 实现的经验,起源是 JVM 启动的时刻。这意味着在下一次 JVM 重新启动后,我肯定会再次看到相同的数字。
所以用作System.nanoTime
标识符是一个糟糕的选择。您的应用程序是否碰巧达到了与之前运行时完全相同的纳秒数,这纯属偶然,但您不必冒这个险。请改用 UUID。
TA贡献1812条经验 获得超5个赞
java.util.UUID.randomUUID()可能是线程安全的。
比较不同线程之间System.nanoTime()调用的结果是不安全的。如果许多线程在同一毫秒内运行,则此函数返回相同的毫秒数。
System.currentTimeMillis()也是如此。
比较 System.currentTimeMillis() 和 System.nanoTime(),后者更昂贵,因为它需要更多的 cpu 周期,但也更准确。所以 UUID 应该符合你的目的。
添加回答
举报