【问题标题】:Why Thread.sleep(long mills, int nanos) and Object.wait(long mills, int nanos) actually ignore nanoseconds amount (according to their source code)?为什么 Thread.sleep(long mills, int nanos) 和 Object.wait(long mills, int nanos) 实际上忽略了纳秒量(根据他们的源代码)?
【发布时间】:2022-08-13 04:19:28
【问题描述】:

我在 macOS 上使用 JDK 17。 我查看了Thread.sleep(long mills, int nanos) 和Object.wait(long mills, int nanos) 及其源代码如下:

线程.sleep:

    public static void sleep(long millis, int nanos)
    throws InterruptedException {
        if (millis < 0) {
            throw new IllegalArgumentException(\"timeout value is negative\");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                \"nanosecond timeout value out of range\");
        }

        if (nanos > 0 && millis < Long.MAX_VALUE) {
            millis++;
        }

        sleep(millis);
    }

对象.等待:

    public final void wait(long timeoutMillis, int nanos) throws InterruptedException {
        if (timeoutMillis < 0) {
            throw new IllegalArgumentException(\"timeoutMillis value is negative\");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                \"nanosecond timeout value out of range\");
        }

        if (nanos > 0 && timeoutMillis < Long.MAX_VALUE) {
            timeoutMillis++;
        }

        wait(timeoutMillis);
    }

因此,根据代码,纳米量实际上被忽略了——如果它大于零,那么磨机只会增加。 这是为什么? 是不是因为我的系统不支持纳米分辨率?

  • TLDR:Javadoc for sleep 说,\“...取决于系统计时器和调度程序的精度和准确性。\”他们\'通过允许您将时间指定到纳秒级来为 API 提供面向未来的验证,但他们\' re 还允许当前的实现不太准确。
  • 如果您需要高精度计时,那么您应该使用real-time edition of Java,在一些real-time OS 上运行。

标签: java multithreading


【解决方案1】:

请改用 LockSupport.parkNanos。在 Linux 下,这将为您提供 50us 的分辨率。 https://hazelcast.com/blog/locksupport-parknanos-under-the-hood-and-the-curious-case-of-parking/

【讨论】:

    【解决方案2】:

    根据System#nanoTime 的javadoc:

    此方法提供纳秒精度,但不一定提供纳秒分辨率(即值更改的频率)——除了分辨率至少与currentTimeMillis() 一样好外,不做任何保证

    所有这一切都是说,虽然System#nanoTime 会为您提供以纳秒为单位的时间,但不一定是准确的时间。相反,时间将至少与System#currentTimeMillis 一样准确。因此,System#nanoTime 在连续调用中偶尔会返回错误值(例如returning a lower value than a previous result)。

    为此,增加所需的毫秒数以确保等待的持续时间超过所需的纳秒数比实际检查System#nanoTime 更简单。

    在 Object#wait 的 javadoc 中也注意到了这一点:

    nanos - 额外时间,以纳秒为单位,范围 0-999999。

    和Thread#sleep:

    nanos - 0-999999 额外的纳秒睡眠时间

    这样纳秒的数量不能超过额外的毫秒,允许他们在必须等待额外的纳秒时简单地将毫秒增加 1。

    【讨论】:

      猜你喜欢
      • 2014-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-13
      • 2013-09-24
      • 2012-01-27
      相关资源
      最近更新 更多