Thread.sleep()实现

今天我接受了一次采访,我向候选人询问了关于Thread.sleep()Object.wait()之间区别的常见和基本问题。 我希望他回答类似这样的事情 ,但他说这些方法基本上都是一样的,而且很可能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)这样有用的调用。 根据这篇文章对调度程序管理有意义:

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

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

你知道在Thread.sleep()实现中没有使用定时等待的任何其他原因吗?

人们可以很容易地说奥卡姆的剃刀切向另一个方向。 假定JDK底层的JVM的正常/预期实现在大多数情况下将java’threads’绑定到本机线程,并且将线程置于hibernate状态是底层平台的基本function。 如果线程代码本来是原生的,为什么要在java中重新实现呢? 最简单的解决方案是使用已经存在的function。

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

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

你知道在Thread.sleep()实现中没有使用定时等待的任何其他原因吗?

因为本机线程库提供了一个非常好的睡眠function: 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技术已经取得了显着进步,并且过去绿色线程的任何好处都被擦除了多年来业绩增长。

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

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

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