wait()和sleep()之间的区别

Gee*_*eek 1158 java multithreading sleep java-threads

一个wait()sleep()在线程之间有什么区别?

我的理解是wait()-ing Thread仍处于运行模式并使用CPU周期但是sleep()-ing不会消耗任何CPU周期吗?

为什么我们 wait()sleep():如何实现他们在一个较低的水平有什么不同?

oxb*_*kes 808

A wait可以被notify正在等待的另一个调用监视器的线程"唤醒",而sleep不能.此外,wait(和notify)必须在synchronized监视器对象的块中发生,而sleep不是:

Object mon = ...;
synchronized (mon) {
    mon.wait();
} 
Run Code Online (Sandbox Code Playgroud)

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

synchronized (mon) { mon.notify(); }
Run Code Online (Sandbox Code Playgroud)

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

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

另一点是,你叫waitObject本身(即您等待对象的监视器上),而你打电话sleepThread.

另一个问题是,你可以得到虚假唤醒wait(即,正在等待简历没有明显原因的线程).您应该始终wait在某些条件下旋转,如下所示:

synchronized {
    while (!condition) { mon.wait(); }
}
Run Code Online (Sandbox Code Playgroud)

  • 不,它不能.它只能被打断. (129认同)
  • @Geek - 为什么世界上你说wait()会浪费CPU周期? (26认同)
  • 中断旨在作为一种机制,轻轻地鼓励线程完全停止运行并取消剩余的操作.`wait` /`notify`通常用于等待某个其他线程完成任务,或等待直到满足某个条件. (24认同)
  • 睡眠线程也可以通过notify()唤醒.? (21认同)
  • 我仔细阅读了所有的答案,但我仍然觉得有点缺少信息.许多人写下了Javadoc中的定义以及两个英语单词的含义,但我不明白为什么我应该使用睡眠而不是等待?两者之间的基准和速度差异是什么?如果我可以做我能用睡眠做的一切,我为什么要选择睡眠呢? (12认同)
  • 在中断时,您必须知道要中断哪个线程.当您调用notify时,您只需要对象,并且您不关心是否有任何其他线程在此对象上"等待".wait/notify用于通信,而sleep用于,ehm,sleep. (6认同)
  • wait()不仅挂起进程,而且如果这个进程有任何共享资源/锁,它必须给它们,直到它可以恢复执行. (3认同)
  • 是的,"还必须在监视器对象上同步的块中发生等待(和通知),而睡眠不会".如果不在synchronized块中使用wait/nitify,它将抛出java.lang.IllegalMonitorStateException. (2认同)

Rob*_*anu 320

没有提到的一个关键区别是,睡觉时一个线程并没有释放它持有,同时等待释放的对象的锁锁wait()被称为上.

synchronized(LOCK) {
    Thread.sleep(1000); // LOCK is held
}


synchronized(LOCK) {
    LOCK.wait(); // LOCK is not held
}
Run Code Online (Sandbox Code Playgroud)

  • 等待仅释放您调用*wait()的对象的锁定.它不释放任何*其他*锁. (99认同)
  • 你实际上并不需要在锁内调用睡眠 - 锁和等待/通知齐头并进,但锁和睡眠是无关的. (15认同)
  • @oxbow_lakes - 我会说你不应该用锁睡觉,很少有用例.只是想指出差异. (7认同)
  • @RobertMunteanu,你的回答误导性地声称`sleep`持有*java*lock,但事实并非如此.为了公平比较,我们将比较`synchronized(OUTER_LOCK){Thread.sleep(1000); 使用`synchronized(OUTER_LOCK){synchronized(LOCK){LOCK.wait();}}`我们可以看到两条指令都没有释放`OUTER_LOCK`.如果有任何区别,我们可以说'sleep`没有明确**使用***java*lock,但问题是询问"它们的实现如何在较低级别变化?" 引文结束. (5认同)
  • @Pacerier`wait()`与它调用的最内部锁的条件相关联,在你的代码示例中,`wait()`只能释放`LOCK`而不是`OUTER_LOCK`.无论如何,这就是Java监视器的设计方式.公平的比较是`synchronized(OUTER_LOCK){synchronized(LOCK){Thread.sleep(1000); `和`synchronized(OUTER_LOCK){synchronized(LOCK){LOCK.wait(); }.在这种情况下,`sleep()`将保持两个锁,而`wait()`将释放`LOCK`但仍保持`OUTER_LOCK` (2认同)

E-r*_*ich 232

我觉得这篇文章很有帮助.它把之间的差异Thread.sleep(),Thread.yield()以及Object.wait()对人类而言.报价:

这一切最终都归结为操作系统的调度程序,它将时间片分配给进程和线程.

sleep(n)说:"我已完成了我的时间片,请不要再给我另一个至少n毫秒."操作系统甚至没有尝试安排睡眠线程,直到请求的时间过去.

yield()他说:"我已完成了我的时间片,但我还有工作要做."操作系统可以自由地立即给线程另一个时间片,或者给一些其他线程或处理CPU放弃线程刚刚放弃.

wait()说:"我完成了我的时间片.在有人调用notify()之前,不要给我另一个时间片."与此同时sleep(),操作系统甚至不会尝试安排你的任务,除非有人打电话notify()(或其他一些其他唤醒场景发生).

线程在执行阻塞IO时以及在其他一些情况下也会丢失剩余的时间片.如果一个线程在整个时间片中工作,那么操作系统会强制控制,就像yield()调用一样,以便其他进程可以运行.

您很少需要yield(),但如果您有一个具有逻辑任务边界的计算量大的应用程序,插入yield() 可能会提高系统响应性(以时间为代价 - 上下文切换,甚至只是操作系统和返回,不是免费的).一如既往地衡量和测试您关心的目标.

  • @Jonathan在答案中没有提到监视器,这是因为`sleep`与任何其他Java方法调用相比没有任何关于监视器的特殊行为,也就是说,它不以任何方式交互或修改它们.如果你想对监视器说些什么,你应该指定`wait`将除了上面说的那样之外,暂时放弃对它被调用的对象的锁定. (2认同)

est*_*ani 65

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

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

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

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

总而言之,您通常sleep()用于时间同步和wait()多线程同步.

它们可以在底层操作系统中以相同的方式实现,或者根本不实现(因为以前版本的Java没有真正的多线程;可能一些小型虚拟机也没有这样做).不要忘记在VM上运行Java,因此您的代码将根据其运行的VM/OS/HW进行不同的转换.


roo*_*ler 52

在这里,我列出了几个wait()sleep()方法之间的重要区别.
PS: 还要点击链接查看图书馆代码(内部工作,只需稍微玩一下以便更好地理解).

等待()

  1. wait() 方法释放锁.
  2. wait()Object类的方法.
  3. wait() 是非静态方法 - public final void wait() throws InterruptedException { //...}
  4. wait()应通知notify()notifyAll()方法.
  5. wait() 需要从循环中调用方法以处理误报.

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

睡觉()

  1. sleep() 方法不释放锁.
  2. sleep()java.lang.Thread类的方法.
  3. sleep() 是静态方法 - public static void sleep(long millis, int nanos) throws InterruptedException { //... }
  4. 在指定的时间后,sleep()完成.
  5. sleep()最好不要从循环调用(即参见下面的代码).
  6. sleep()可以从任何地方打电话.没有具体要求.

参考:等待和睡眠之间的差异

用于调用wait和sleep方法的代码片段

synchronized(monitor){
    while(condition == true){ 
        monitor.wait()  //releases monitor lock
    }

    Thread.sleep(100); //puts current thread on Sleep    
}
Run Code Online (Sandbox Code Playgroud)

线程转换到不同的线程状态

  • 好的我需要阅读更多有关线程调度的内容,因为我找不到notify()或notifyAll()唤醒睡眠线程的示例,只有中断()这样做.所有示例都将notify()和notifyAll()与等待某个监视器对象的线程相关联. (2认同)

Ngu*_*Dat 28

在完成等待和睡眠之后,我总结了一些不同的关键注释,首先使用wait()和sleep()查看样本:

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

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

让清晰一些关键的笔记:

  1. 请致电:
    • wait():调用持有HandObject Object的当前线程
    • sleep():调用线程执行任务获取啤酒(是类方法因此影响当前运行的线程)
  2. 同步:
    • wait():当同步多线程访问同一个Object(HandObject)时(需要多个线程之间的通信(线程执行编码,线程执行获取啤酒)访问同一个对象HandObject)
    • sleep():等待条件继续执行(等待啤酒可用)
  3. 保持锁定:
    • wait():释放其他对象的锁有机会执行(HandObject是免费的,你可以做其他工作)
    • sleep():保持锁定至少t次(或直到中断)(我的工作仍未完成,我继续保持锁定并等待某些条件继续)
  4. 唤醒条件:
    • wait():直到从对象调用notify(),notifyAll()
    • sleep():直到至少时间到期或调用中断
  5. estani指出,最后一点是使用:

通常使用sleep()进行时间同步,使用wait()进行多线程同步.

如果我错了,请纠正我.


Pre*_*raj 23

wait()和sleep()之间的区别

  • 根本区别在于它wait()来自Object并且sleep()是静态方法Thread.

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

  • wait()通常用于线程间通信,而sleep()用于在执行时引入暂停.

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

  • 要再次启动线程wait(),您必须调用notify()notifyAll().至于sleep(),线程在指定的时间间隔后开始.

相似

  • 两者都使当前线程进入Not Runnable状态.
  • 两者都是本机方法.


Vik*_*pta 18

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

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

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

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

但是,如果sleep()这是一种方法,用于将过程保持几秒钟或您想要的时间.因为您不需要激发任何notify()notifyAll()方法来获取该线程.或者您不需要任何其他线程来回调该线程.就像你想要的东西应该在几秒钟之后发生,比如在用户轮到你的游戏之后,你希望用户等到计算机播放然后你可以提到这个sleep()方法.

在访谈中经常被问到的另一个重要的区别是:sleep()属于Thread阶级,wait()属于Object阶级.

这些是sleep()和之间的所有区别wait().

并且两种方法之间存在相似性:它们都是检查语句,因此您需要尝试catch或throws来访问这些方法.

我希望这能帮到您.


小智 16

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

Thread.sleep()将当前线程发送到"Not Runnable"状态一段时间.线程保持它已获取的监视器 - 即,如果线程当前处于同步块或方法中,则其他线程无法进入此块或方法.如果另一个线程调用t.interrupt()它将唤醒睡眠线程.

请注意,sleep是一种静态方法,这意味着它总是会影响当前线程(正在执行sleep方法的线程).一个常见的错误是调用t.sleep()t是不同的线程; 即使这样,它是当前线程将睡眠,而不是t线程.

t.suspend()已弃用.使用它可以暂停当前线程以外的线程.挂起的线程会保留其所有监视器,并且由于此状态不可中断,因此容易出现死锁.

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


Ita*_*man 14

等待和睡眠是两回事:

  • sleep()线程停止工作指定的持续时间.
  • wait()线程停止工作,直到通知等待的对象,通常由其他线程.

  • 等待不会浪费CPU周期. (9认同)
  • 如果浪费CPU周期,那么wait()的实现会非常糟糕.wait/notify用于非线程通信. (3认同)
  • @Pacerier这两个结构用于不同的目的.如果你想让一个线程在一段固定的时间内停止你使用`sleep`,如果你想让它停止直到某个输入来自另一个你使用`wait` /`notify`.`interrupt`旨在表示线程应该停止执行它正在做的事情并终止它.它由`sleep`,`wait`处理,但也阻塞了I/O函数(你可以通过调用方法`Thread.interrupted()`来实现具有相同行为的函数).至于性能,功能通常针对他们设计的目标进行优化. (2认同)

pvl*_*spk 11

sleep是一种方法Thread,wait是一种方法Object,wait/notify也是一种在Java中同步共享数据的技术(使用监视器),但它sleep是一种简单的线程暂停自身的方法.


Ree*_*nda 8

sleep()是一种方法,用于将进程保持几秒或你想要的时间但是在wait()方法的情况下,线程进入等待状态,并且在我们调用notify()之前它不会自动返回notifyAll的().

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

Thread.sleep()将当前线程发送到"Not Runnable"状态一段时间.线程保持它已获取的监视器 - 即,如果线程当前处于同步块或方法中,则其他线程无法进入此块或方法.如果另一个线程调用t.interrupt(),它将唤醒睡眠线程.请注意,sleep是一种静态方法,这意味着它总是会影响当前线程(正在执行sleep方法的线程).一个常见的错误是调用t.sleep(),其中t是一个不同的线程; 即使这样,它是当前线程将睡眠,而不是t线程.

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

synchronized(LOCK) {   
   Thread.sleep(1000); // LOCK is held
}

synchronized(LOCK) {   
   LOCK.wait(); // LOCK is not held
}
Run Code Online (Sandbox Code Playgroud)

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

Call on:

  • wait():调用一个对象; 当前线程必须在锁定对象上同步.
  • sleep():调用一个线程; 总是当前正在执行线程

Synchronized:

  • wait():当同步多个线程逐个访问同一个Object时.
  • sleep():当同步的多个线程等待睡眠线程的睡眠时.

Hold lock:

  • wait():释放其他对象的锁,以便有机会执行.
  • sleep():如果指定超时或有人中断,则保持锁定至少t次.

Wake-up condition:

  • wait():直到从对象调用notify(),notifyAll()
  • sleep():直到至少时间到期或调用interrupt().

Usage:

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

参考:差异sleepwait


Roe*_*ler 6

waitsleep方法有很大不同:

想想看,这个名字在这方面令人困惑; 然而,sleep是一个标准的名称,wait是喜欢WaitForSingleObject还是WaitForMultipleObjects赢的API中.

  • 但是我们可以打断*睡眠*我们不能吗?那么睡眠/中断与等待/通知的区别是什么? (3认同)
  • 您可以打扰一个正在睡觉的人,但是您只能通知一个正在等待的人。线程是相同的。 (2认同)

Rat*_*rya 5

简单来说,wait is wait直到某个其他线程调用你,而sleep在某段指定的时间内"不执行next statement".

此外,sleep是Thread类中的静态方法,它在线程上运行,而wait()在Object类中并在对象上调用.

另一点,当你在某个对象上调用wait时,涉及的线程会同步对象然后等待.:)

  • Notify用于线程之间的通信.要调用wait,需要一些对象,对它进行同步,然后调用wait.要通知,您需要其他线程在*same*对象上进行同步,并调用notify. (2认同)

小智 5

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

wait()方法.

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

2)在其他线程调用同一个锁上的notify()或notifyAll()方法后,线程重新获得锁定.

3)必须在synchronized块内调用wait()方法.

4)始终在对象上调用wait()方法.

5)通过调用notify()或notifyAll()方法,其他线程可以唤醒等待线程.

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

sleep()方法

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

2)sleep()方法可以在synchronized块内外调用.

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

4)其他线程无法唤醒睡眠线程.如果这样做,线程将抛出InterruptedException.

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