Thread.sleep()实现

时间:2012-01-30 23:40:03

标签: java multithreading sleep wait

今天我接受了一次采访,我问了候选人关于Thread.sleep()Object.wait()之间差异的常见和基本问题。我希望他能回答like this这样的问题,但他说这些方法基本上都是一样的,很可能Thread.sleep在其中使用Object.wait(),但sleep本身并没有不需要外部锁定。这不是一个正确的答案,因为在JDK 1.6中,此方法具有以下签名。

public static native void sleep(long millis) throws InterruptedException;

但我的第二个想法是,这不是那么荒谬。可以使用定时等待来实现相同的效果。请查看以下代码段:

public class Thread implements Runnable {
       private final Object sleepLock = new Object();

     // other implementation details are skipped

       public static void sleep(long millis) throws InterruptedException {
            synchronized (getCurrentThread().sleepLock){
                getCurrentThread().sleepLock.wait(millis);
            }
        }

在这种情况下,sleepLock是一个特别用于sleep方法内的同步块的对象。我假设Sun / Oracle工程师知道Occam的剃须刀,所以sleep有故意本地实现,所以我的问题是为什么它使用本机调用。

我想出的唯一想法是假设有人可能会找到有用的调用,例如Thread.sleep(0)。根据{{​​3}}

对调度程序管理有意义
  

这具有清除当前线程的量子并将其置于队列末尾以获得其优先级的特殊效果。换句话说,所有具有相同优先级的可运行线程(以及具有更高优先级的线程)将有机会在下一个给定CPU时间产生线程之前运行。

因此synchronized块将带来不必要的开销。

您是否知道在Thread.sleep()实施中未使用定时等待的其他原因?

4 个答案:

答案 0 :(得分:9)

人们可以很容易地说Occam的Razor会削减其他方式。假定JDK底层的JVM的正常/预期实现在大多数情况下将java'threads'绑定到本机线程,并且将线程置于睡眠状态是底层平台的基本功能。如果线程代码本来是原生的,为什么要在java中重新实现呢?最简单的解决方案是使用已存在的功能。

其他一些注意事项: 在现代JVM中,无可争议的同步可以忽略不计,但并非总是这样。它曾经是一个相当“昂贵”的操作来获取该对象监视器。

如果你在java代码中实现线程休眠,并且你实现它的方式也没有绑定到本机线程等待,操作系统必须保持调度该线程以便运行检查是否有时间唤醒的代码起来。正如评论中所说的那样,对于你在现代JVM上的例子显然不是这样,但很难说 1)Thread类首次被指定的时候可能已经存在和期望的东西。 和 2)如果该断言适用于每个平台,则可能曾经想要实现JVM。

答案 1 :(得分:7)

  

您是否知道在Thread.sleep()实施中不使用定时等待的其他原因?

因为本机线程库提供了非常好的睡眠功能:http://www.gnu.org/software/libc/manual/html_node/Sleeping.html

要了解原生线程的重要性,请从http://java.sun.com/docs/hotspot/threads/threads.html

开始
  

1.1版基于绿色线程,此处不予介绍。绿色线程是VM中的模拟线程,在进入1.2及更高版本的本机OS线程模型之前使用。绿色线程可能在Linux上有一个优势(因为您不必为每个本机线程生成一个进程),但自1.1版本以来VM技术已经取得了显着进步,并且过去绿色线程的任何好处都被删除了多年来业绩增长。

答案 2 :(得分:2)

spurious wakeups之前,Thread.sleep()不会被提前唤醒。如果使用Object.wait(),要正确地执行它(即确保你等待足够的时间),你需要一个循环查询经过的时间(例如System.currentTimeMillis()),以确保你等待足够。

从技术上讲,您可以使用Object.wait()实现Thread.sleep()的相同功能,但是您需要编写更多代码才能正确执行。

This也是一个相关且有用的讨论。

答案 3 :(得分:0)

当一个线程被称为sleep方法时,该线程将被添加到睡眠队列中。如果计算时钟频率为100HZ,则意味着每10ms当前运行过程将被中断。保留线程的当前上下文后,它将减少每个线程的值(-10ms)。当它为零时,线程将移至“等待CPU”队列。当时间片进入该线程时,它将再次运行。另外,由于此操作不会立即开始运行,因此实际睡眠时间大于它设置的值。