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

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

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

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


当前回答

sleep()是一个用来保持进程几秒钟或你想要的时间的方法,但如果wait()方法线程处于等待状态,它不会自动返回,直到我们调用notify()或notifyAll()。

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

thread .sleep()将当前线程发送到“不可运行”状态一段时间。线程保留它获得的监视器——也就是说,如果线程当前在一个同步块或方法中,没有其他线程可以进入这个块或方法。如果另一个线程调用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
}

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

呼吁:

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

同步:

wait():同步的多个线程逐个访问同一个对象。 Sleep():当同步的多个线程等待休眠线程的休眠。

持有锁:

Wait():释放锁,让其他对象有机会执行。 Sleep():如果指定超时或有人中断,则保持锁定至少t次。

唤醒条件:

wait():直到调用notify(), notifyAll()从对象 Sleep():直到至少超时或调用interrupt()。

用法:

Sleep():用于时间同步和; Wait():用于多线程同步。

参考:差别睡眠和等待

其他回答

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

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

wait()和sleep()的区别

最根本的区别是wait()是Object的非静态方法,sleep()是Thread的静态方法。 主要的区别是wait()释放锁,而sleep()在等待时不释放任何锁。 Wait()用于线程间通信,而sleep()通常用于在执行时引入暂停。 wait()应该从synchronise内部调用,否则我们会得到一个IllegalMonitorStateException,而sleep()可以在任何地方调用。 要从wait()再次启动线程,必须无限期地调用notify()或notifyAll()。至于sleep(),线程肯定会在指定的时间间隔后启动。

相似之处

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

Wait()是在同步方法中给出的 而sleep()是在非同步方法中给出的,因为wait()方法会释放对象上的锁,而sleep()或yield()会释放对象上的锁。

从oracle文档页面的wait()方法的对象:

public final void wait()

导致当前线程等待,直到另一个线程调用该对象的notify()方法或notifyAll()方法。换句话说,这个方法的行为就像简单地执行调用wait(0)一样。 当前线程必须拥有该对象的监视器。线程释放该监视器的所有权并等待,直到另一个线程通知等待该对象监视器的线程被唤醒 可能会出现中断和虚假唤醒 此方法只能由该对象的监视器的所有者的线程调用

这个方法抛出

IllegalMonitorStateException -如果当前线程不是对象的监视器的所有者。 InterruptedException——如果任何线程在当前线程等待通知之前或期间中断了当前线程。抛出此异常时,当前线程的中断状态将被清除。

从oracle文档页关于Thread类的sleep()方法:

public static void sleep(long millis)

使当前正在执行的线程休眠(暂时停止执行)指定的毫秒数,这取决于系统计时器和调度器的精度和准确性。 线程不会失去任何监视器的所有权。

这个方法抛出:

IllegalArgumentException -如果millis的值为负 InterruptedException -如果任何线程中断了当前线程。抛出此异常时,当前线程的中断状态将被清除。

其他关键区别:

Wait()是一个非静态方法(实例方法),不同于静态方法sleep()(类方法)。

一个尚未提及的关键区别是:

sleep()不会释放它在线程上持有的锁, 同步(锁){ thread . sleep (1000);// LOCK被持有 } Wait()释放它在对象上持有的锁。 同步(锁){ LOCK.wait ();// LOCK不被持有 }