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

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

我是否知道wait() ing 线程仍处于运行模式并使用 CPU 周期,但是sleep() ing 不会消耗任何 CPU 周期正确吗?

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

答案

一个wait可以 “唤醒” 被另一个线程调用notify ,其正在上而等待在监视器上sleep不了。同样,必须在监视对象上synchronized的块中发生wait (并notify ),而sleep不会:

Object mon = ...;
synchronized (mon) {
    mon.wait();
}

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

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

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

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

另一点是,您在Object本身上调用wait (即,在对象的监视器上等待),而在Thread上调用sleep

还有一点是,您可以从wait得到虚假的唤醒(即,正在等待的线程无故恢复运行)。 以下情况下 ,您应该始终wait旋转

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

没有提到的一个关键区别是在睡眠时线程不会释放其持有的锁,而在对象上等待释放锁wait()调用上。

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


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

我发现这篇文章很有帮助。它将Thread.sleep()Thread.yield()Object.wait()的区别用人为术语。去引用:

最终,这一切都将归结到 OS 的调度程序,后者将时间片交给进程和线程。

sleep(n)说: “我已经处理完时间片了,请不要在至少 n 毫秒内再给我另一个时间片。”在请求的时间过去之前,操作系统甚至不会尝试调度睡眠线程。

yield()说: “我已经完成了时间片的工作,但是我仍然有工作要做。” OS 可以自由地立即给线程另一个时间片,或者给其他线程或处理 CPU,而放弃的产量线程。

wait()说: “我已经完成了时间片。不要给我一个时间片,直到有人调用 notify()”sleep()操作系统甚至不会尝试安排你的任务,除非有人来电notify()或其他一些唤醒情况之一发生时)。

当线程执行阻塞 IO 以及其他一些情况时,线程也会丢失其时间片的其余部分。如果一个线程遍历整个时间片,则 OS 会强行进行控制,就像调用了yield()一样,以便其他进程可以运行。

您很少需要yield() ,但是如果您有一个具有逻辑任务边界的计算繁重的应用程序,则插入yield() 可能会改善系统响应能力(以时间为代价 - 上下文切换,甚至只是向 OS 和向后切换,都不会)免费)。一如既往地根据您关心的目标进行衡量和测试。

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

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

sleep()使线程像以前一样进入睡眠状态,它只是打包上下文并在预定的时间内停止执行。因此,为了在适当的时间之前将其唤醒,您需要了解线程引用。这在多线程环境中并不常见。它主要用于时间同步(例如,在 3.5 秒内准确唤醒)和 / 或硬编码的公平性(只需睡眠一会儿,然后让其他线程工作)。

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

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

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

在这里,我列出了wait()sleep()方法之间的一些重要区别。
PS: 也单击链接以查看库代码(内部工作,请稍作练习以更好地理解)。

等待()

  1. wait()方法释放锁定。
  2. wait()Object类的方法。
  3. wait()是非静态方法 - public final void wait() throws InterruptedException { //...}
  4. 应该通过notify()notifyAll()方法notify() wait()
  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()可以从任何地方调用。没有具体要求。

参考: 等待和睡眠之间的区别

调用等待和睡眠方法的代码片段

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

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

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

在等待和睡眠之后,我总结出一些不同的主要说明,首先使用 wait()和 sleep()来研究示例:

Example1 :使用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();
}

让我们澄清一些主要注意事项:

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

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

如果我错了,请纠正我。

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

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

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

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

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

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

相似点

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

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

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

这只是一个清晰而基本的解释,如果您想要的不止这些,请继续阅读。

在的情况下, wait()方法的线程进入等待状态,它会不会回来,直到自动我们所说的notify()方法(或notifyAll()如果你有更多的则处于等待状态一个线程,并要唤醒所有的这些线程)。并且您需要同步或对象锁定或类锁定来访问wait()notify()notifyAll()方法。还有一点, wait()方法用于线程间通信,因为如果线程进入等待状态,则需要另一个线程来唤醒该线程。

但是在sleep()情况下,这是一种用于将进程保留几秒钟或所需时间的方法。因为您不需要激发任何notify()notifyAll()方法来获取该线程。或者,您不需要任何其他线程来回调该线程。就像如果您希望某事在几秒钟后发生,例如在用户回合之后在游戏中发生一样,您希望用户等到计算机播放后,便可以提及sleep()方法。

还有一个在采访中经常问到的重要差异: sleep()属于Thread类,而wait()属于Object类。

这些都是sleep()wait()之间的区别。

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

我希望这能帮到您。

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

Thread.sleep()将当前线程发送到“不可运行”状态一段时间。该线程保留其已获取的监视器 - 即,如果该线程当前在同步块或方法中,则没有其他线程可以进入该块或方法。如果另一个线程调用t.interrupt() ,它将唤醒睡眠线程。

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

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

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

等待和睡眠是两件事:

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