Thread.sleep()实现

wax*_*wax 28 java multithreading sleep wait

今天,我有一个采访上,我问候选人很平常和基本的问题有关的区别Thread.sleep()Object.wait().我希望他回答类似这样的事情,但他说这些方法基本上都是一样的,很可能Thread.sleepObject.wait()在里面使用,但sleep本身并不需要外部锁定.这不是一个正确的答案,因为在JDK 1.6中,此方法具有以下签名.

public static native void sleep(long millis) throws InterruptedException;
Run Code Online (Sandbox Code Playgroud)

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

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);
            }
        }
Run Code Online (Sandbox Code Playgroud)

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

我想出的唯一想法是假设有人可能会找到有用的调用Thread.sleep(0).根据这篇文章对调度程序管理有意义:

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

所以一个synchronized块会带来不必要的开销.

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

Aff*_*ffe 9

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

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

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


Mik*_*uel 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技术已经取得了显着进步,并且过去绿色线程的任何好处都被删除了多年来业绩增长.