0

假设我在 Thread 中有一个以下循环(我们称之为Thread-A)。

while (threadCondition) {
  System.out.println(new Date());
  Thread.sleep(1000);
}

并假设其他Thread-B将导致应用程序挂起的时间 >=2sec (因为其他一些 Thread (我们称之为Thread-B,因为没有足够的 CPU 资源,可用内存不足等)

是否有可能当Thread-A在提到的 >=2 秒之后开始动作时,System.out.println(new Date())将一个接一个地执行两次(“立即”,没有睡眠),并打印相同的日期(具有相同的数字毫)两次?

4

5 回答 5

3

JVM 不保证睡眠时间的精度。它可能在 996 毫秒、1003 毫秒或 2000 毫秒后唤醒 - 都是有效时间

但是,不能保证这些睡眠时间是精确的,因为它们受到底层操作系统提供的设施的限制。此外,睡眠周期可以通过中断来终止,我们将在后面的部分中看到。在任何情况下,您都不能假设调用 sleep 会在指定的时间段内暂停线程 ——source

没有跟踪线程真正休眠的时间量。

sleep()遇到另一个时,线程将在唤醒之前等待另一个(或多或少)1000 毫秒。

由于睡眠时间不准确,您的应用程序可能在时间 10.000 打印了一次日期,并在 10.981 再次打印了相同的日期,即使几乎过了一秒。

另外:请记住, sleep() 方法可能会被中断。如果异常处理代码在这个循环中,睡眠可能会被中断,异常被吞没并打印两个日期。

于 2013-09-02T13:37:37.973 回答
2

如果两个调用new Date()可以同时给出

  • 如果在同一毫秒内
  • 如果它们在时钟的分辨率范围内。例如,在 Windows XP 上约为 16 毫秒。
  • 如果时间由 NTP 或类似更改。例如,时间可以倒退并重复。
  • 如果您使用字节码检测来覆盖时间。例如,因为您想要一个测试驱动时钟。
  • 如果两个线程相隔 2 秒开始但同时结束,则它们可以同时打印。
  • 如果线程 B 先启动,然后线程 A 启动,则线程 B 可以在线程 A 之后打印一个时间。仅仅因为它开始较早并不意味着它会先完成。
  • 如果默认情况下它们出现在同一秒内,则 new Date() 将打印相同的日期。
于 2013-09-02T13:40:27.367 回答
1

不, Thread.sleep(...) 会在指定的时间内延迟执行。没有内部计数器跟踪“当前时间”,由于线程暂时被推到后台,这可能会变得不同步,这似乎是您的想法。

于 2013-09-02T13:23:03.523 回答
1

我不相信这是可能的。

当应用程序由于您提到的任何原因挂起时,它会从它停止的代码行继续执行。

代码导致现在可能是多余的挂起的事实是无关紧要的。您并不真的希望 JVM 分析您的代码...

于 2013-09-02T13:23:13.097 回答
0

为什么不使用System.nanoTime()(即 PC 中的高分辨率性能计数器)代替date(). 而且,如果您将 sleep 放入 if 并正确编写条件,它将不会使线程休眠。

于 2013-09-02T13:51:16.877 回答