【问题标题】:Java milli second precisionJava毫秒精度
【发布时间】:2009-12-02 11:10:10
【问题描述】:

是否有一个 Java API/建议可以用来代替 System.currentTimeMillis() 在 Windows 上以毫秒精度获取当前时间 - 要求是两个后续调用之间的睡眠时间为 1ms 应该给出两个不同的时间 - 目前我需要显式睡眠 15 毫秒才能获得不同的时间

【问题讨论】:

  • 你能用当前时间,然后在每个循环中将毫秒数加 1,然后将其写入数据库(可能不准确,但它会是唯一的)..
  • System.currentTimeMillis() 取决于,操作系统如何测量时间。
  • 感谢您的输入-可能会使用内部计数器实现并以预定的时间间隔重新同步时钟-注意:也许我最初应该以不同的方式表达问题-对时间戳的要求不是生成 uid - 用于版本控制、审计以及查看特定时间和日期的历史数据等

标签: java


【解决方案1】:

不要试图利用时间来创造独特的价值。使用数据库为记录生成一个唯一的 id(我假设是键)。要么使用自动递增字段,要么创建一个单独的表,其中包含一个包含可以安全锁定和更新的计数器的记录。

虽然您可能会得到一个可行的解决方案,但依靠时机来防止资源冲突最终会赶上您。

【讨论】:

  • 我同意,但我处于无法进行任何数据库设计更改的阶段 - 最坏的情况是延迟 15 毫秒
  • @prabhackar,注意:如果系统时间由于某种原因而中断,您也会遇到问题。我希望您验证时间戳不会倒退。 :)
【解决方案2】:

从 Java 1.5 开始,您可以使用 System.nanoTime() 进行更高精度的微基准测试。由于它所基于的固定时间可能会发生变化(有关方法,请参阅 Javadoc),因此将其与 System.currentTimeMillis() 结合使用可能是有意义的,例如

String time = System.currentTimeMillis() + "" + System.nanoTime();

【讨论】:

  • 相信它只用于经过的时间
  • 对,要获得时间戳,将它与 System.currentTimeMillis() 结合使用可能更有意义
【解决方案3】:

这是一个 Windows 限制。如果您在其他操作系统上调用 System.currentTimeMillis() ,您将获得更高的精度。

我的建议是不要使用时间戳作为唯一性来源。使用专为解决此问题而设计的 oracle 序列。否则使用线程名称 + 时间戳 (yuk)。

或者您可以使用 System.nanoTime(),但它只对时差有用,而不是绝对时间。

【讨论】:

    【解决方案4】:

    从 java 1.5 开始,您可以使用 java.util.UUID 生成唯一 ID。

    例如

       public static void main(String[] args)
       {
          System.out.println("uuid=" + UUID.randomUUID().toString());
          System.out.println("uuid=" + UUID.randomUUID().toString());
       }
    

    【讨论】:

      【解决方案5】:

      currentTimeMillis() 调用的分辨率取决于底层操作系统,不应依赖于在您的情况下创建唯一标记。考虑使用一个 UID 单例,它可以为您提供一个长值,每次调用都会增加一,然后使用它。

      【讨论】:

        【解决方案6】:

        为什么你需要时代独一无二?

        在事务开始时花点时间,然后为每个插入添加一个 MS。

        【讨论】:

        • 数据版本控制 - 没有这样的事务 - 有时可能会有两个线程更新同一实体的数据,然后我在没有 15 毫秒延迟的情况下遇到问题
        • 然后使用主键,而不是当前日期。
        【解决方案7】:

        在这里区分准确性和精确度很重要。 System.currentTimeMillis() 具有毫秒精度,但不能保证精度,因为它从底层操作系统获取,操作系统从硬件获取,并且不同的硬件时钟具有不同的精度。

        将其用于数据版本控制是一个坏主意,因为即使您具有毫秒精度,如果两件事情在同一毫秒内发生,您仍然会冒偶尔发生冲突的风险。

        【讨论】:

          【解决方案8】:

          虽然这与问题没有直接关系,但我从 cmets 中了解到最初的尝试是生成一些版本标识符。

          这当然是个坏主意,这里的其他海报对此进行了详细说明。

          如果您不能使用数据库,那么更好的办法是使用 AtomicIntegerAtomicLong -- 然后您可以调用 getAndIncrement()incrementAndGet() 而不必担心任何可能的时间问题出现。

          【讨论】:

            【解决方案9】:

            绝对时间分辨率的 15 毫秒限制是您的操作系统和中断率的一个特性。我知道对于 Linux,有一个内核补丁可以将分辨率提高到 1 毫秒(甚至可能是微秒?),但不确定 Windows。正如其他人评论的那样,可以使用 System#nanoTime() 解决相对时间(目前为微秒精度)。无论哪种方式,您都应该考虑使用 db 键(或类似键)来分配唯一键。

            链接

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2023-03-25
              • 2017-01-27
              • 2014-08-07
              • 2015-06-25
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多