如果线程实际上睡得太久,可以跳过后续的sleep()吗?

时间:2013-09-02 13:15:51

标签: java multithreading thread-safety jvm

我们假设我在一个线程中有一个跟随循环(我们称之为 Thread-A )。

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

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

主题-A 在提到的> = 2秒之后开始行动时,System.out.println(new Date())可能会一个接一个地执行两次('立即',没有睡觉),并将两次打印相同的日期(具有相同的毫秒数)?

5 个答案:

答案 0 :(得分:3)

JVM不保证睡眠时间的精确度。它可能会在996ms,1003ms或2000ms后唤醒 - 所有都是有效时间

  

然而,这些睡眠时间并不能保证准确,因为   它们受底层操作系统提供的设施限制。   此外,我们将看到,中断可以终止休眠期   在后面的部分。无论如何,你不能假设调用睡眠   将在指定的时间段内暂停该主题 -   source

没有跟踪线程真正睡觉的时间。

当遇到另一个sleep()时,线程将在醒来之前等待另一个(并且或多或少)1000ms。

由于睡眠时间不准确,因此有可能在10.000时你的应用程序打印了一次日期,并且在10.981它再次打印了相同的日期,尽管几乎已经过了一秒钟。

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

答案 1 :(得分:2)

如果

,对new Date()的两次调用可以给出相同的时间
  • 如果是在同一毫秒
  • 如果它们在时钟分辨率范围内。例如在Windows XP上它是~16 ms。
  • 如果NTP或类似时间改变了时间。例如时间可以倒退并重复。
  • 如果您使用字节代码检测来覆盖时间。例如因为你想要一个测试驱动的时钟。
  • 如果两个线程分开2秒但同时完成,则可以同时打印。
  • 如果线程B首先开始而线程A开始之后,线程B可以在线程A之后打印一个时间。仅仅因为它更早开始并不意味着它将首先完成。
  • new Date()默认情况下会在同一秒内打印相同的日期。

答案 2 :(得分:1)

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

答案 3 :(得分:1)

我认为不可能。

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

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

答案 4 :(得分:0)

为什么不使用System.nanoTime()(即PC中的高分辨率性能计数器)代替date()。如果你将睡眠置于if并正确地写入条件,它将不会睡眠线程。