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

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

为什么我们同时使用wait()和sleep()?

它们的实现在较低级别上有什么不同?


当前回答

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

在sleep()期间调用interrupt()总是抛出异常(例如InterruptedException),而 在wait()期间调用notify()不会。

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

其他回答

我发现这篇文章很有帮助。它将Thread.sleep(), Thread.yield()和Object.wait()之间的区别放在人类术语中。引用:

这一切最终都会传到操作系统的调度程序 将时间片分发给进程和线程。 sleep(n)表示“我已经用完了我的时间片,请不要给我 再来一次,至少n毫秒。”操作系统甚至不会尝试这样做 调度睡眠线程,直到请求的时间过去。 yield()表示“我已经完成了我的时间片,但我仍然有工作要做 做的。”操作系统可以立即给线程另一个时间片, 或者给CPU的其他线程或进程生成线程 就这么放弃了。 wait()表示“我完成了我的时间片。别再给我了 时间片,直到有人调用notify()。”与sleep()一样,操作系统不会这样做 甚至尝试调度您的任务,除非有人调用notify()(或其中之一) 还有其他一些醒来的场景)。 线程在执行时也会丢失剩余的时间片 阻塞IO和其他一些情况下。如果线程工作 在整个时间片中,操作系统强制控制大致为 如果已经调用yield(),则其他进程可以运行。 你很少需要yield(),但是如果你有一个计算量很大的应用程序 逻辑任务边界,插入yield()可以改善系统 响应性(以时间为代价——上下文切换,甚至只是 到操作系统并返回,不是免费的)。衡量和测试你的目标 在乎,一如既往。

让我们假设你正在听到歌曲。

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

如果你完成了这首歌,它会停止,直到你选择播放按钮(notify())它才会播放,即由当前歌曲调用的wait()。

在这两种情况下,歌曲都进入等待状态。

在研究了wait和sleep之后,我总结了一些不同的关键注意事项,首先看一下使用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();
}

让我们明确一些关键的注意事项:

呼吁: wait():调用当前持有handdobject对象的线程 sleep():在线程上调用执行任务获取啤酒(是类方法,因此影响当前运行的线程) 同步: wait():当同步多线程访问同一对象(HandObject)时(当多个线程之间需要通信时(线程执行编码,线程执行获取啤酒)访问同一对象(HandObject) sleep():当等待状态继续执行时(等待啤酒可用) 持有锁: wait():释放锁,让其他对象有机会执行(HandObject是空闲的,你可以做其他工作) sleep():保持锁至少t次(或直到中断)(我的工作仍然没有完成,我继续持有锁,等待一些条件继续) 唤醒条件: wait():直到调用notify(), notifyAll()从对象 Sleep():直到至少超时或调用中断 最后一点是当estani表示:

通常使用sleep()进行时间同步,使用wait()进行时间同步 multi-thread-synchronization。

如果我说错了,请指正。

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

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

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

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

总而言之,通常使用sleep()进行时间同步,使用wait()进行多线程同步。

它们可以在底层操作系统中以同样的方式实现,也可以完全不实现(因为以前版本的Java没有真正的多线程;可能一些小的虚拟机也不这样做)。别忘了Java是在VM上运行的,所以你的代码会根据所运行的VM/OS/HW的不同而转换成不同的东西。

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

Wait()方法会导致当前线程在指定的时间内进入阻塞状态或直到notify,但在这种情况下,线程会释放对象的锁(这意味着其他线程可以执行调用对象的任何同步方法)。