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()
实现中使用定时等待的其他原因吗?
人们可以很容易地说,奥卡姆的剃刀削减了另一种方式。 JVM底层JDK的正常/预期实现被假定为在大多数情况下将Java线程绑定到本地线程,并且让线程进入休眠状态是底层平台的基本功能。 为什么在java中重新实现它,如果线程代码是本地的呢? 最简单的解决方案是使用已经存在的功能。
其他一些考虑因素:现代JVM中未经验证的同步可以忽略不计,但事实并非如此。 它曾经是一个相当“昂贵”的操作来获取该对象监视器。
如果你在Java代码中实现线程休眠,并且实现它的方式也不会绑定到本地线程等待,那么操作系统必须保持调度该线程以运行检查是否需要唤醒的代码。 正如在评论中被忽略的那样,这对于你在现代JVM中的例子显然不是这样,但是很难说1)当Thread类首次被指定时,可能已经存在和期望的东西。 2)如果这个断言适用于每个人可能想要实现JVM的平台。
你知道没有在Thread.sleep()
实现中使用定时等待的其他原因吗?
因为本地线程库提供了一个非常好的睡眠函数:http://www.gnu.org/software/libc/manual/html_node/Sleeping.html
要理解为什么本地线程很重要,请从http://java.sun.com/docs/hotspot/threads/threads.html开始。
版本1.1基于绿色线程,不会在此处介绍。 绿色线程是虚拟机内的模拟线程,在使用1.2或更高版本的本机OS线程模型之前使用。 绿色线程在Linux上可能有一个优点(因为您不必为每个本地线程产生一个进程),但是自从1.1版以来,VM技术已经显着提升,并且绿色线程在过去的任何好处都被多年来表现增加。
Thread.sleep()不会被虚假唤醒提前唤醒。 如果使用Object.wait(),要正确地做到这一点(即确保您有足够的时间),您需要一个循环查询经过的时间(例如System.currentTimeMillis()),以确保足够的等待时间。
从技术上讲,你可以用Object.wait()实现Thread.sleep()的相同功能,但是你需要编写更多的代码才能正确执行。
这也是一个相关和有用的讨论。
链接地址: http://www.djcxy.com/p/92147.html