为了账号安全,请及时绑定邮箱和手机立即绑定

我可以使用 nanoTime 而不是 randomUUID 吗?

我可以使用 nanoTime 而不是 randomUUID 吗?

qq_花开花谢_0 2023-02-23 18:05:12
我正在编写一个每隔几秒向订阅者返回数据的过程。我想为订阅者创建一个唯一的 ID:producer -> subsriber1          -> subsriber2使用有什么区别:java.util.UUID.randomUUID()System.nanoTime()System.currentTimeMillis()纳米时间会永远独一无二吗?随机UUID怎么样?
查看完整描述

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。


查看完整回答
反对 回复 2023-02-23
?
ABOUTYOU

TA贡献1812条经验 获得超5个赞

java.util.UUID.randomUUID()可能是线程安全的

比较不同线程之间System.nanoTime()调用的结果是不安全的。如果许多线程在同一毫秒内运行,则此函数返回相同的毫秒数。

System.currentTimeMillis()也是如此。

比较 System.currentTimeMillis() 和 System.nanoTime(),后者更昂贵,因为它需要更多的 cpu 周期,但也更准确。所以 UUID 应该符合你的目的。


查看完整回答
反对 回复 2023-02-23
?
MMMHUHU

TA贡献1834条经验 获得超8个赞

我想是的,你可以使用System.nanoTime()as id。我已经对其进行了测试并且没有遇到重复。 PS 但我强烈建议您使用 UUID。



查看完整回答
反对 回复 2023-02-23
  • 3 回答
  • 0 关注
  • 132 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信