今天,我有一个采访上,我问候选人很平常和基本的问题有关的区别Thread.sleep()和Object.wait()。我以为他会回答类似这样的,但他说,这些方法基本上是一样的,而且极有可能Thread.sleep是用Object.wait()在它里面,但sleep本身并不需要外部锁。这不是完全正确的答案,因为在JDK 1.6中此方法具有以下签名。
Thread.sleep()
Object.wait()
Thread.sleep
sleep
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本机实现是故意的,所以我的问题是为什么它使用本机调用。
sleepLock
我想到的唯一想法是假设某人可能会找到有用的调用,例如Thread.sleep(0)。根据本文,对调度程序管理很有意义:
Thread.sleep(0)
这具有清除当前线程的数量并将其放在优先级级别的队列末端的特殊效果。换句话说,具有相同优先级的所有可运行线程(以及具有更高优先级的那些线程)将有机会在下一个给定的CPU时间之前让产生的线程运行。
因此,synchronized块将产生不必要的开销。
synchronized
您是否知道在Thread.sleep()执行中不使用定时等待的其他原因?
可以很容易地说Occam的Razor削减了另一种方式。假定大多数情况下,基于Java的JDK的JVM的正常/预期实现都是将Java“线程”绑定到本机线程上,并且使线程处于休眠状态是基础平台的基本功能。如果无论如何线程代码都是本地的,为什么还要在Java中重新实现它?最简单的解决方案是使用已经存在的功能。
其他一些注意事项:在现代JVM中,无争议的同步可以忽略不计,但并非总是如此。过去,获取该对象监视器是一项相当“昂贵”的操作。
如果在Java代码中实现线程休眠,并且实现方式也未绑定到本机线程等待,则操作系统必须继续调度该线程,以便运行检查是否需要唤醒的代码。正如注释中所散列的那样,对于现代JVM上的示例而言,这显然不是正确的,但是很难说1)首次以这种方式指定Thread类时可能已经存在并期望发生什么。2)如果该断言适用于每个平台,则可能有人曾经想在其上实现JVM。