如何让 java 中的线程休眠几毫秒?

How to sleep a thread in java for few milliseconds?

我想让一个线程休眠 1 毫秒。我曾经在 java 代码中实现睡眠,其中 Thread.sleep(x) 是 x 我想要睡眠的毫秒数。但是,我看到它不会在几毫秒(1 毫秒)内工作,因为睡眠放弃了线程的时间片。也就是说,线程实际停止的最短时间由内部系统计时器确定,但不少于 10 或 25 毫秒(取决于 OS)。

有什么方法可以在几毫秒内实现它,例如10 毫秒还是 1 毫秒?

我认为 os 不会让你那样做。我最好的选择是做一个可能会消耗一些时间的小循环。但也要注意 java 编译器,因为它可能并且可以通过执行死代码分析来消除无意义的循环。所以只要把循环的结果存起来,在循环里,做一些除法或者取模os,这些都是非常耗时的

但总的来说,这完全是一个 hack,你通常应该避免做这么小的延迟。通常它们不会改善用户体验,但仍会导致代码复杂

“放弃线程的时间片”和“睡眠”的意思大致相同。如果你想要一个不“休眠”的 delay,那么你需要你的线程在这段时间内“自旋”,什么都不做。例如,

static void spin(long delay_in_milliseconds) {
    long delay_in_nanoseconds = delay_in_milliseconds*1000000;
    long start_time = System.nanoTime();
    while (true) {
        long now = System.nanoTime();
        long time_spent_sleeping_thus_far = now - start_time;
        if (time_spent_sleeping_thus_far >= delay_in_nanoseconds) {
            break;
        }
    }
}

调用 spin(n) 将消耗 CPU 时间 n 毫秒,这是在不“放弃时间片”的情况下延迟线程的唯一方法。


P.S.,你说,“我看到它 [sleep()] 行不通......”这是为什么?你看见什么了?您是否真的 测量了 程序的性能,发现它并不令人满意?还是您的程序未能满足某些要求 hard real-time requirement? If your program has real-time requirements, then you might want to read about the "Real-time Specification for Java" (RTSJ)。

另请参阅,https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/System.html#nanoTime()

就像已经提到的其他发帖者一样,您没有太多的控制权。尤其是 Thread.sleep。稍微可靠一点的方法是LockSupport.parkNanos。在 Linux.

上,这应该给你至少 50 us 的粒度

有关详细信息,请参阅这个优秀的 post

另请记住,如果其他进程是 运行,则很容易出现多毫秒暂停。中断处理也会造成很大的干扰。当然,Java GC 和 JVM 的各种其他方面,如(重新)jitting、偏向锁撤销、调用堆栈采样(取决于机制)等也可能是暂停的原因。

如果所需的延迟在一个循环中并且只有 每个循环的平均延迟 很重要 考虑使用 OS时间测量(例如 System.nanotime())来测量 sleep() 延迟,然后每第 n 个循环调用 sleep() 来平均 ms 的正确分数。例如,每 3 个循环的 sleep(1) 平均为 sleep(1) 延迟的 1/3。总延迟的测量可以与总循环计数一起保存,因此每个循环的平均延迟是已知的。然后还可以包括定期修正。