关于Java:wait() 和 sleep()之间的区别

Difference between wait() and sleep()

在线程中,wait()sleep()有什么区别?

我是否理解wait()ing线程仍处于运行模式并使用CPU周期,但sleep()ing不使用任何CPU周期是正确的?

为什么我们同时拥有wait()sleep():它们的实现在较低的级别上有什么不同?


一个wait可以被另一个在监视器上调用notify的线程"唤醒",而一个sleep不能。另外,waitnotify必须发生在监视器对象的synchronized块中,而sleep不:

1
2
3
4
Object mon = ...;
synchronized (mon) {
    mon.wait();
}

此时,当前正在执行的线程将等待并释放监视器。另一个线程可以

1
synchronized (mon) { mon.notify(); }

(在同一个mon对象上)第一个线程(假设它是唯一等待监视器的线程)将被唤醒。

如果监视器上有多个线程在等待,您也可以调用notifyAll–这将唤醒所有线程。但是,只有一个线程能够抓取监视器(记住,waitsynchronized块中)并继续执行—其他线程将被阻塞,直到它们能够获取监视器的锁为止。

另一个观点是,你在Object上称wait(即你等待对象的监视器),而在Thread上称sleep

还有一点是,您可以从wait中得到虚假的唤醒(即等待的线程没有明显的原因而恢复)。在以下条件下旋转时,应始终使用cx1〔0〕:

1
2
3
synchronized {
    while (!condition) { mon.wait(); }
}


一个尚未提到的关键区别是,当一个线程处于休眠状态时,它所持有的锁不会被释放,而等待会释放对wait()被调用的对象的锁。

1
2
3
4
5
6
7
8
synchronized(LOCK) {
    Thread.sleep(1000); // LOCK is held
}


synchronized(LOCK) {
    LOCK.wait(); // LOCK is not held
}


我发现这篇文章很有用。它把Thread.sleep()Thread.yield()Object.wait()在人类方面的区别。引述:

It all eventually makes its way down to the OS’s scheduler, which
hands out timeslices to processes and threads.

sleep(n) says"I’m done with my timeslice, and please don’t give me
another one for at least n milliseconds." The OS doesn’t even try to
schedule the sleeping thread until requested time has passed.

yield() says"I’m done with my timeslice, but I still have work to
do." The OS is free to immediately give the thread another timeslice,
or to give some other thread or process the CPU the yielding thread
just gave up.

wait() says"I’m done with my timeslice. Don’t give me another
timeslice until someone calls notify()." As with sleep(), the OS won’t
even try to schedule your task unless someone calls notify() (or one of
a few other wakeup scenarios occurs).

Threads also lose the remainder of their timeslice when they perform
blocking IO and under a few other circumstances. If a thread works
through the entire timeslice, the OS forcibly takes control roughly as
if yield() had been called, so that other processes can run.

You rarely need yield(), but if you have a compute-heavy app with
logical task boundaries, inserting a yield() might improve system
responsiveness (at the expense of time — context switches, even just
to the OS and back, aren’t free). Measure and test against goals you
care about, as always.


这里有很多答案,但我找不到任何提到的语义区别。

这与线程本身无关;这两种方法都是必需的,因为它们支持非常不同的用例。

sleep()像以前一样将线程发送到sleep,它只是打包上下文并在一个预定义的时间内停止执行。所以为了在适当的时间之前唤醒它,您需要知道线程引用。这不是多线程环境中的常见情况。它主要用于时间同步(例如精确地在3.5秒内唤醒)和/或硬编码的公平性(只需休眠一段时间,让其他线程工作)。

相反,wait()是一种线程(或消息)同步机制,允许您通知一个没有存储引用(也不关心)的线程。您可以将其视为发布-订阅模式(wait==subscribe和notify()==publish)。基本上,您使用notify()发送一条消息(甚至可能根本没有收到消息,通常您不在乎)。

综上所述,通常使用sleep()进行时间同步,使用wait()进行多线程同步。

它们可以以相同的方式在底层OS中实现,或者根本没有实现(因为以前版本的Java没有真正的多线程;可能一些小的VM也不这样做)。不要忘记Java在VM上运行,所以你的代码将根据它运行的VM/OS/HW来进行不同的转换。


这里,我列出了wait()sleep()方法之间的几个重要区别。< BR>PS:也可以点击链接来查看库代码(内部工作,只是为了更好地理解而四处游玩)。

WAIT()

  • wait()方法释放锁。
  • wait()Object类的方法。
  • wait()为非静态方法-public final void wait() throws InterruptedException { //...}
  • notify()notifyAll()方法通知wait()
  • 为了处理虚警,需要从循环中调用wait()方法。

  • 必须从同步上下文(即同步方法或块)调用wait()方法,否则将抛出IllegalMonitorStateException

  • 睡眠()

  • sleep()方法不释放锁。
  • sleep()java.lang.Thread类的方法。
  • sleep()是静态方法-public static void sleep(long millis, int nanos) throws InterruptedException { //... }
  • 在规定的时间之后,sleep()完成。
  • sleep()最好不要从循环调用(即参见下面的代码)。
  • 可以从任何地方调用sleep()。没有具体要求。
  • 参考:等待和睡眠的区别

    用于调用Wait and Sleep方法的代码段

    1
    2
    3
    4
    5
    6
    7
    synchronized(monitor){
        while(condition == true){
            monitor.wait()  //releases monitor lock
        }

        Thread.sleep(100); //puts current thread on Sleep    
    }

    thread transition to different thread states


    在处理wait和sleep之后,我总结了一些不同的关键注意事项,首先使用wait()和sleep()查看示例:

    示例1:使用wait()和sleep():

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    synchronized(HandObject) {
        while(isHandFree() == false) {
            /* Hand is still busy on happy coding or something else, please wait */
            HandObject.wait();
        }
    }

    /* Get lock ^^, It is my turn, take a cup beer now */
    while (beerIsAvailable() == false) {
        /* Beer is still coming, not available, Hand still hold glass to get beer,
           don't release hand to perform other task */

        Thread.sleep(5000);
    }

    /* Enjoy my beer now ^^ */
    drinkBeers();

    /* I have drink enough, now hand can continue with other task: continue coding */
    setHandFreeState(true);
    synchronized(HandObject) {
        HandObject.notifyAll();
    }

    请澄清一些关键注意事项:

  • 拜访:
    • wait():对保存handObject对象的当前线程的调用
    • sleep():调用线程execute task get beer(类方法会影响当前运行的线程)
  • 同步的:
    • wait():当同步多线程访问同一对象(handObject)时(当需要多个线程之间的通信(thread execute coding,thread execute get beer)访问同一对象handObject)
    • sleep():等待条件继续执行时(等待啤酒可用)
  • 保持锁定:
    • wait():释放其他对象有机会执行的锁(handObject是空闲的,您可以执行其他任务)
    • sleep():保持锁定至少T次(或直到中断)(我的工作仍然没有完成,我将继续保持锁定并等待某个条件继续)
  • 唤醒条件:
    • wait():直到调用notify(),notifyall()来自对象
    • sleep():直到至少时间到期或调用中断
  • 最后一点是当Estani指出:
  • you normally use sleep() for time-syncronization and wait() for
    multi-thread-synchronization.

    如果我错了,请纠正我。


    wait()和sleep()之间的差异

    • 根本区别在于wait()来自Objectsleep()Thread的静态方法。

    • 主要区别在于,wait()释放锁,而sleep()在等待时不释放任何锁。

    • wait()用于线程间通信,而sleep()一般用于引入执行暂停。

    • 应该从内部同步调用wait(),否则我们得到IllegalMonitorStateException,而sleep()可以在任何地方调用。

    • 要从wait()重新启动线程,必须调用notify()notifyAll()。对于sleep(),,线程在指定的时间间隔后启动。

    相似之处

    • 两者都会使当前线程进入不可运行状态。
    • 两者都是本地方法。

    这是一个非常简单的问题,因为这两种方法的用途完全不同。

    主要的区别是等待释放锁或监视器,而睡眠不释放任何锁或监视器,而等待。wait用于线程间通信,sleep用于引入执行暂停。

    这只是一个清晰而基本的解释,如果你想要更多,那么继续阅读。

    如果wait()方法线程处于等待状态,它将不会自动返回,直到我们调用notify()方法(或notifyAll()方法,如果您有多个线程处于等待状态,并且希望唤醒所有这些线程)。您需要同步或对象锁或类锁来访问wait()notify()notifyAll()方法。还有一件事,wait()方法用于线程间通信,因为如果一个线程进入等待状态,则需要另一个线程来唤醒该线程。

    但对于sleep()来说,这是一种方法,用于将进程保持几秒钟或您想要的时间。因为您不需要激发任何notify()notifyAll()方法来恢复线程。或者您不需要任何其他线程来调用该线程。比如,如果你想让一些事情在几秒钟后发生,比如在一场用户轮到你的游戏中,你想让用户等到电脑开始播放,然后你可以提到sleep()方法。

    还有一个更重要的区别,在采访中经常被问到:sleep()属于Thread类,wait()属于Object类。

    这些都是sleep()wait()之间的差异。

    这两个方法之间有一个相似之处:它们都是被检查的语句,所以您需要尝试catch或throw来访问这些方法。

    我希望这对你有帮助。


    资料来源:http://www.jguru.com/faq/view.jsp?EID=47127

    Thread.sleep() sends the current thread into the"Not Runnable" state
    for some amount of time. The thread keeps the monitors it has aquired
    -- i.e. if the thread is currently in a synchronized block or method no other thread can enter this block or method. If another thread calls t.interrupt() it will wake up the sleeping thread.

    Note that sleep is a static method, which means that it always affects
    the current thread (the one that is executing the sleep method). A
    common mistake is to call t.sleep() where t is a different thread;
    even then, it is the current thread that will sleep, not the t thread.

    t.suspend() is deprecated. Using it is possible to halt a thread other
    than the current thread. A suspended thread keeps all its monitors and
    since this state is not interruptable it is deadlock prone.

    object.wait() sends the current thread into the"Not Runnable" state,
    like sleep(), but with a twist. Wait is called on an object, not a
    thread; we call this object the"lock object." Before lock.wait() is
    called, the current thread must synchronize on the lock object; wait()
    then releases this lock, and adds the thread to the"wait list"
    associated with the lock. Later, another thread can synchronize on the
    same lock object and call lock.notify(). This wakes up the original,
    waiting thread. Basically, wait()/notify() is like
    sleep()/interrupt(), only the active thread does not need a direct
    pointer to the sleeping thread, but only to the shared lock object.


    等待和睡眠是两件不同的事情:

    • sleep()中,线程在指定的持续时间内停止工作。
    • wait()中,线程停止工作,直到等待的对象被通知为止,通常是由其他线程通知的。


    EDOCX1 0是一种EDCOX1×1的方法,EDCOX1×2是EDCOX1×3的一种方法,因此EDCOX1·4是一种在Java中使用监视器同步数据的技术,而EDCOX1·0是一种简单的线程暂停方法。


    sleep()是一种方法,用于将进程保持几秒钟或您想要的时间,但如果wait()方法线程处于等待状态,则在调用notify()或notifyall()之前,它不会自动返回。

    主要区别在于wait()释放锁或监视器,而sleep()在等待时不释放任何锁或监视器。wait用于线程间通信,而sleep通常用于在执行时引入暂停。

    sleep()将当前线程发送到"不可运行"状态一段时间。线程保留它所获取的监视器-即如果线程当前位于同步块或方法中,则其他线程都不能进入此块或方法。如果另一个线程调用t.interrupt(),它将唤醒休眠线程。注意sleep是一个静态方法,这意味着它总是影响当前线程(执行sleep方法的线程)。一个常见的错误是调用t.sleep(),其中t是一个不同的线程;即使这样,它也是当前将休眠的线程,而不是t线程。

    wait()将当前线程发送到"不可运行"状态,就像sleep()一样,但有一个扭曲。wait是对一个对象而不是线程调用的;我们称这个对象为"lock object"。在调用lock.wait()之前,当前线程必须在lock对象上同步;wait()然后释放这个锁,并将线程添加到与锁关联的"wait list"中。稍后,另一个线程可以在同一个锁对象上同步并调用lock.notify()。这会唤醒原始的等待线程。基本上,wait()/notify()类似于sleep()/interrupt(),只有活动线程不需要指向休眠线程的直接指针,而只需要指向共享锁对象。

    1
    2
    3
    4
    5
    6
    7
    synchronized(LOCK) {  
       Thread.sleep(1000); // LOCK is held
    }

    synchronized(LOCK) {  
       LOCK.wait(); // LOCK is not held
    }

    让我们对以上所有点进行分类:

    Call on:

    • wait():对对象的调用;当前线程必须在锁定对象上同步。
    • sleep():对线程的调用;始终执行线程。

    Synchronized:

    • wait():当同步多个线程逐个访问同一对象时。
    • sleep():同步多个线程时,等待休眠线程的休眠结束。

    Hold lock:

    • wait():释放锁,让其他对象有机会执行。
    • sleep():如果指定了超时或有人中断,则锁定至少T次。

    Wake-up condition:

    • wait():直到调用notify(),notifyall()来自对象
    • sleep():直到至少时间到期或调用中断()。

    Usage:

    • sleep():用于时间同步和;
    • wait():用于多线程同步。

    参考号:Diff sleepwait


    waitsleep方法非常不同:

    • sleep无法"唤醒",
    • wait在等待期间有一种"唤醒"的方式,通过另一个线程调用notifynotifyAll

    想一想,名称在这方面是混淆的,但是sleep是标准名称,wait就像win api中的WaitForSingleObjectWaitForMultipleObjects


    从这篇文章:http://javaconceptoftheday.com/difference-between-wait-and-sleep-methods-in-java/

    方法()。

    1)调用wait()方法的线程释放它持有的锁。

    2)其他线程在同一锁上调用notify()或notifyall()方法后,线程重新获得锁。

    3)wait()方法必须在同步块内调用。

    4)wait()方法总是在对象上调用。

    5)等待线程可以通过调用notify()或notifyall()方法被其他线程唤醒。

    6)要调用wait()方法,线程必须具有对象锁。

    睡眠(法)

    1)调用sleep()方法的线程不会释放它持有的锁。

    2)可以在同步块内部或外部调用sleep()方法。

    3)sleep()方法总是在线程上调用。

    4)休眠线程不能被其他线程唤醒。如果这样做,线程将抛出InterruptedException。

    5)要调用sleep()方法,线程不需要有对象锁。


    简单地说,wait是等待直到其他线程调用您,而sleep是在指定的一段时间内"不执行下一条语句"。

    此外,sleep是线程类中的静态方法,它在线程上操作,而wait()在对象类中并在对象上调用。

    另一点是,当您在某个对象上调用wait时,线程会同步该对象,然后等待。:)


    睡眠/中断和等待/通知之间的一个潜在的巨大区别是

    • sleep()期间调用interrupt()总是抛出一个异常(例如interruptedexception),而
    • wait()期间打电话给notify()没有。

    在不需要时生成异常是低效的。如果线程之间的通信速率很高,那么如果您一直在调用interrupt,就会产生很多异常,这是对CPU的浪费。


  • wait()Object类的一种方法。sleep()Thread类的一种方法。

  • sleep()允许线程进入sleep状态x毫秒。当线程进入休眠状态时,it doesn’t release the lock

  • wait()允许线程释放锁,goes to suspended state允许线程释放锁。当notify()notifAll()方法为为同一对象调用。


  • 您是正确的-sleep()导致该线程"休眠",CPU将关闭并处理其他线程(也称为上下文切换),而我认为wait使CPU处理当前线程。

    我们两者都有,因为尽管让其他人在不使用CPU的情况下使用它似乎是明智的,但实际上,上下文切换有一个开销-取决于睡眠时间的长短,在CPU周期中切换线程可能比让线程在几毫秒内不做任何事情要贵得多。

    还要注意,睡眠会强制上下文切换。

    另外,一般来说,不可能控制上下文切换,在等待期间,操作系统可能(并且将等待更长的时间)选择处理其他线程。


    这些方法用于不同的事情。

    1
    2
    3
    Thread.sleep(5000);   // Wait until the time has passed.

    Object.wait();        // Wait until some other thread tells me to wake up.

    可以中断thread.sleep(n),但必须通知object.wait()。可以指定最长的等待时间:Object.wait(5000),这样就可以使用waitto、er、sleep,但是您必须考虑锁。

    两种方法都不会在休眠/等待时使用CPU。

    这些方法是使用本机代码实现的,使用类似的构造,但方式不同。

    寻找你自己:本地方法的源代码可用吗?文件/src/share/vm/prims/jvm.cpp是…


    这里,wait()将处于等待状态,直到它被另一个线程通知,但是作为sleep()将有一段时间..之后,它将自动转移到就绪状态…


    wait()和sleep()的区别?

    线程()一旦它的工作完成,那么只有它向每个人释放锁。直到它永远不会向任何人释放锁。

    1
      Sleep() take the key, its never release the key to anyone, when its work completed then only its release then only take the key waiting stage threads.

    WAITE()当它进入等待阶段时,它将根据参数释放密钥并等待一些秒。

    例如:

    你的右手拿着咖啡,你可以拿另一个同一只手的人,你什么时候放下,然后在这里只拿另一个同类型的东西。也。这是睡眠()你睡觉的时候没有工作,你只是在睡觉。这里也一样。

    WAIT()当你被放下再拿一个时,意味着你在等待,那就是等待。

    您正在播放电影或您的系统中的任何内容与播放机相同,您不能一次播放多个电影或歌曲,这就是这里,当您关闭并选择另一个时,任何人的电影或歌曲都意味着同时被称为等待。


    wait释放锁,sleep不释放锁,当notifynotifyAll被调用时,处于等待状态的线程就有资格被唤醒。但是,对于sleep,线程保持锁,只有在睡眠时间结束后才有资格使用。


    Object的wait()方法的Oracle文档页面:

    1
    public final void wait()
  • 使当前线程等待,直到另一个线程为此对象调用notify()方法或notifyAll()方法。换句话说,这个方法的行为就好像它只是执行调用wait(0)一样。
  • 当前线程必须拥有此对象的监视器。线程释放此监视器的所有权并等待,直到另一个线程通知等待此对象监视器唤醒的线程为止。
  • 中断和虚假唤醒是可能的。
  • 此方法只能由该对象监视器的所有者线程调用
  • 此方法引发

  • IllegalMonitorStateException—如果当前线程不是对象监视器的所有者。

  • InterruptedException—如果任何线程在当前线程等待通知之前或期间中断了当前线程。当抛出此异常时,当前线程的中断状态将被清除。

  • Thread类的sleep()方法的Oracle文档页:

    1
    public static void sleep(long millis)
  • 使当前执行的线程在指定的毫秒数内休眠(暂时停止执行),这取决于系统计时器和调度程序的精度和准确性。
  • 线程不会丢失任何监视器的所有权。
  • 此方法引发:

  • IllegalArgumentException—如果毫秒值为负数

  • InterruptedException—如果有线程中断了当前线程。当抛出此异常时,当前线程的中断状态将被清除。

  • 其他主要区别:

    wait()是一种非静态方法(实例方法),与静态方法sleep()不同(类方法)。


    sleep()方法使当前线程在指定的时间内从运行状态移动到块状态。如果当前线程拥有任何对象的锁,那么它会一直持有它,这意味着其他线程无法在该类对象中执行任何同步方法。

    wait()方法使当前线程在指定时间或通知之前进入阻塞状态,但在这种情况下,线程释放对象的锁(这意味着其他线程可以执行调用对象的任何同步方法)。


    在我看来,这两种机制的主要区别在于睡眠/中断是处理线程的最基本方式,而等待/通知是一种抽象,旨在使线程之间的通信更加容易。这意味着睡眠/中断可以做任何事情,但是这个特定的任务很难做。

    为什么等待/通知更合适?以下是一些个人考虑事项:

  • 它强制集中。它允许协调一组线程与单个共享对象之间的通信。这大大简化了工作。

  • 它强制同步。因为它使程序员将等待/通知的调用包装在一个同步块中。

  • 它独立于线程的起源和编号。使用这种方法,您可以任意添加更多线程,而无需编辑其他线程或跟踪现有线程。如果使用sleep/interrupt,首先需要保留对休眠线程的引用,然后手动逐个中断它们。

  • 从现实生活中可以很好地解释这一点的一个例子是一家经典的餐厅和员工之间交流的方法:服务员把顾客的要求放在一个中心位置(软木板、桌子等),敲钟,厨房的工作人员来接受这样的要求。一旦有菜准备好了,厨房的工作人员就再按一下门铃,这样服务员就知道了,并把菜送到顾客那里。


    关于睡眠不释放锁和等待的例子

    这里有两个类:

  • 主:包含主方法和两个线程。
  • singleton:这是singleton类,有两个静态方法getInstance()和getInstance(boolean iswait)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    public class Main {

    private static Singleton singletonA = null;
    private static Singleton singletonB = null;

    public static void main(String[] args) throws InterruptedException {

    Thread threadA = new Thread() {
        @Override
        public void run() {

            singletonA = Singleton.getInstance(true);

        }
    };

    Thread threadB = new Thread() {
        @Override
        public void run() {
            singletonB = Singleton.getInstance();

            while (singletonA == null) {
                System.out.println("SingletonA still null");
            }

            if (singletonA == singletonB) {
                System.out.println("Both singleton are same");
            } else {
                System.out.println("Both singleton are not same");
            }

        }
    };

    threadA.start();
    threadB.start();

     }
    }
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    public class Singleton {

        private static Singleton _instance;

        public static Singleton getInstance() {

        if (_instance == null) {
            synchronized (Singleton.class) {
                if (_instance == null)
                    _instance = new Singleton();
            }
        }
        return _instance;

    }

    public static Singleton getInstance(boolean isWait) {

        if (_instance == null) {
            synchronized (Singleton.class) {
                if (_instance == null) {
                    if (isWait) {
                        try {
                            // Singleton.class.wait(500);//Using wait
                            Thread.sleep(500);// Using Sleep
                            System.out.println("_instance :"
                                    + String.valueOf(_instance));
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                    _instance = new Singleton();
                }
            }
        }
        return _instance;

     }
    }

    现在运行这个示例,您将得到以下输出:

    1
    2
    _instance :null
    Both singleton are same

    这里,由threada和threadb创建的单例实例是相同的。这意味着苏莱达在外面等着苏莱达释放它的锁。

    现在通过注释thread.sleep(500);方法并取消注释singleton.class.wait(500);来更改singleton.java。这里是因为singleton.class.wait(500);方法threada将释放所有的获取锁并进入"不可运行"状态,threadb将被更改为进入同步块。

    现在再次运行:

    1
    2
    3
    4
    5
    6
    7
    8
    SingletonA still null
    SingletonA still null
    SingletonA still null
    _instance :com.omt.sleepwait.Singleton@10c042ab
    SingletonA still null
    SingletonA still null
    SingletonA still null
    Both singleton are not same

    这里,由threada和threadb创建的singleton实例是不同的,因为threadb在同步块中进行了更改,并且在500毫秒后,threada从其最后一个位置开始并创建了另一个singleton对象。


    应该从synchronized块调用:wait()方法总是从synchronized块调用,即wait()方法在调用对象之前需要锁定对象监视器。但是,可以从外部同步块调用sleep()方法,即sleep()方法不需要任何对象监视器。

    IllegalMonitorStateException:如果在不获取对象锁的情况下调用wait()方法,则运行时将引发IllegalMonitorStateException,但sleep()方法从未引发此类异常。

    属于哪个类:wait()方法属于java.lang.Object类,sleep()方法属于java.lang.Thread类。

    在对象或线程上调用:对对象调用wait()方法,但对线程调用sleep()方法,而不是对对象。

    线程状态:在对象上调用wait()方法时,保持对象监视器的线程从运行状态变为等待状态,只有在该对象上调用notify()notifyAll()方法时才能返回可运行状态。稍后线程调度程序会安排该线程从可运行状态转到运行状态。当在线程上调用sleep()时,它将从运行状态变为等待状态,并且可以在睡眠时间结束时返回可运行状态。

    当从synchronized块调用时:当调用wait()方法时,线程离开对象锁。但当从同步块或方法线程调用sleep()方法时,它不会留下对象锁。

    更多参考资料


    同步方法中给出了wait()。由于wait()方法释放对象上的锁,而sleep()yield()不释放lock(),因此在非同步方法中给出sleep()


    实际上,所有这些都是在Java文档中清楚地描述的(但是我在阅读了答案之后才意识到这一点)。

    http://docs.oracle.com/javase/8/docs/api/index.html:

    wait()-当前线程必须拥有此对象的监视器。线程释放此监视器的所有权,并等待另一个线程通知等待此对象监视器通过调用notify方法或notifyall方法。然后线程等待直到它可以重新获得监视器的所有权并继续执行。

    sleep()-根据系统计时器和调度程序的精度和准确性,使当前执行的线程休眠(临时停止执行)指定的毫秒数。线程不会丢失任何监视器的所有权。


    使用超时值等待可以在超时值结束时唤醒,或通知较早者(也可以是中断),而睡眠则在超时值结束时唤醒,或中断以较早者为准。不带超时值的wait()将一直等待,直到通知或中断为止。


    • 方法wait(1000)使当前线程休眠一秒钟。
      • 如果线程接收到notify()notifyAll()方法调用,它可以休眠不到1秒。
    • sleep(1000)的调用会使当前线程休眠1秒钟。
      • 另外,休眠线程不保存任何资源锁。但是等待线程是这样的。


    假设你在听歌曲。

    只要当前歌曲正在运行,下一首歌就不会播放,即sleep()由下一首歌调用

    如果您完成了歌曲,它将停止播放,直到您选择播放按钮(notify())它将不播放,即等待()由当前歌曲调用。

    在这两种情况下,歌曲将等待状态。