关于System.nanoTime()

System.nanoTime()的返回值只和进程已运行的时间有关, 不受调系统时间影响.

以前测试netty中的一个时间轮工具类(HasedTimeWheel)发现它不支持调系统时间, 比如一个任务是6点执行, 提交到时间轮后, 把系统时间调到7点,. 任务不会立即执行, 但是看HasedTimeWheel的代码感觉在设计上是支持调时间的(即调到7点后任务应该立即执行), 一顿测试后发现此类以System.nanoTime()作为"当前时间", 要想支持调时间, 只需要把System.nanoTime()替换成System.currentTimeMillis()(相关时间单位也要改).

 

System.nanoTime()的返回值要用相减是否大于0来判断调用的先后顺序, 但不能用>或<来判断.

System.nanoTime()返回的数值实际是64位无符号数, 随着进程运行时间增长, 溢出后再从0开始, 赋值给long类型相当于当做补码数(有符号数)使用, 其值循环规律如下:

最小负数 -> 0 -> 最大正数 -> 最小负数 -> ...

假设有两次先后顺序未知的调用, 且两次调用时间间隔小于2^63ns (约200+year)
long t1 = System.nanoTime();
long t2 = System.nanoTime();

  • 如果t1和t2都是正数或t1和t2都是负数, 则t1和t2的差不会超过2^63, 它们相减不会溢出, t1>t2 <=> t1-t2>0, 且较大的数一定是后一次调用返回的, 所以用相减比较和><运算符比较都可以 ;
  • 如果t1和t2一正一负, 设t2是正数, 对比它们作为无符号数时的值, 可以知道负数t1才是后一次调用返回的, 所以由t2>t1得出t2是后一次调用是错误的. 另外我们假设了两次调用间隔小于2^63, t2-t1的值一定大于2^63 (放在long里面是负数), 所以有t2-t1<0, 此时用相减来判断仍然是正确的.

 

JDK里System.nanoTime()方法的注释

    /**
     * Returns the current value of the running Java Virtual Machine's
     * high-resolution time source, in nanoseconds.
     *
     * <p>This method can only be used to measure elapsed time and is
     * not related to any other notion of system or wall-clock time.
     * The value returned represents nanoseconds since some fixed but
     * arbitrary <i>origin</i> time (perhaps in the future, so values
     * may be negative).  The same origin is used by all invocations of
     * this method in an instance of a Java virtual machine; other
     * virtual machine instances are likely to use a different origin.
     *
     * <p>This method provides nanosecond precision, but not necessarily
     * nanosecond resolution (that is, how frequently the value changes)
     * - no guarantees are made except that the resolution is at least as
     * good as that of {@link #currentTimeMillis()}.
     *
     * <p>Differences in successive calls that span greater than
     * approximately 292 years (2<sup>63</sup> nanoseconds) will not
     * correctly compute elapsed time due to numerical overflow.
     *
     * <p>The values returned by this method become meaningful only when
     * the difference between two such values, obtained within the same
     * instance of a Java virtual machine, is computed.
     *
     * <p> For example, to measure how long some code takes to execute:
     *  <pre> {@code
     * long startTime = System.nanoTime();
     * // ... the code being measured ...
     * long estimatedTime = System.nanoTime() - startTime;}</pre>
     *
     * <p>To compare two nanoTime values
     *  <pre> {@code
     * long t0 = System.nanoTime();
     * ...
     * long t1 = System.nanoTime();}</pre>
     *
     * one should use {@code t1 - t0 < 0}, not {@code t1 < t0},
     * because of the possibility of numerical overflow.
     *
     * @return the current value of the running Java Virtual Machine's
     *         high-resolution time source, in nanoseconds
     * @since 1.5
     */
    public static native long nanoTime();

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值