我可以使用nanoTime代替randomUUID吗?

时间:2019-06-28 15:53:03

标签: java

我正在编写一个过程,每隔几秒钟将数据返回给订阅者。我想为订户创建一个唯一的ID:

producer -> subsriber1
         -> subsriber2

使用之间有什么区别

  • java.util.UUID.randomUUID()
  • System.nanoTime()
  • System.currentTimeMillis()

纳米时间会永远独一无二吗?随机UUID呢?

3 个答案:

答案 0 :(得分:2)

UUID

128-bit UUID的发明完全是为了您的目的:在一台或多台计算机上生成标识符,而无需通过中央机构进行协调。

理想情况下,您将使用原始的版本1 UUID或其在版本2、3和5中的变体。原始文件采用主机计算机网络接口的MAC地址,并将其与当前时刻以及一个较小的任意数字组合在一起调整主机时钟后递增。这种方法消除了重复的任何实际问题。

Java没有捆绑用于生成这些版本的实现。我认为Java设计师在泄露位置,时间和MAC地址方面存在隐私和安全问题。

对于版本4,Java仅带有一个生成器实现。在这种类型中,除6位之外的所有128位都是随机生成的。如果使用加密强度高的随机生成器,则此版本足以在大多数常见情况下使用而无需担心冲突。

理解122位是真正很大的数字范围(5.316911983139664e + 36)。 64位的范围为18,446,744,073,709,552,000(18位数)。剩下的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 undecillion

尽管如此,如果您有权生成除4以外的UUID版本,请使用它。例如,在诸如Postgres之类的数据库系统中,数据库服务器可以在包括版本1在内的各种版本中生成UUID号。或者您可以找到用于生成此类UUID的Java库,尽管该库可能与平台无关(其中可能包含本机代码)。

System.nanoTime

请注意,System.nanoTime与当前日期和时间无关。引用Javadoc:

  

此方法只能用于测量经过时间,与系统或挂钟时间的任何其他概念无关。

System.nanoTime功能仅返回一个long数字,距离 some 起源以纳秒为单位,但是起源不是 指定

Java规范中唯一的保证是,在JVM运行时,其原点不会改变。因此,您知道应用程序执行期间该数字一直在增加。除非到达limit of a long,否则计数器将翻转。如果起点为零,则可能需要292年(2 ^ 63纳秒)的翻转-但是同样,未指定起点。

根据我使用的特定Java实现的经验,其起源是JVM启动的时刻。这意味着在下一次JVM重新启动后,我肯定会再次看到相同的数字。

因此,使用System.nanoTime作为标识符是一个糟糕的选择。您的应用程序碰巧碰巧碰巧与前一次运行中看到的完全相同的纳秒数是纯正的机会,但您不必冒这个机会。 改为使用UUID。

答案 1 :(得分:1)

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

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

System.currentTimeMillis()也是如此。

比较System.currentTimeMillis()和System.nanoTime(),后者更昂贵,因为它需要更多的cpu周期,但也更准确。因此,UUID应该可以满足您的目的。

答案 2 :(得分:0)

我认为是的,您可以将System.nanoTime()用作id。我已经测试过了,没有遇到重复。 附言但我强烈建议您使用UUID。