wait()
和之间的sleep()
线程有什么区别?
我的理解是 wait()
-ing线程仍处于运行模式并使用CPU周期,但是sleep()
-ing不会消耗任何CPU周期吗?
我们为什么同时 拥有wait()
和sleep()
:它们的实现在较低的水平如何变化?
wait()
和之间的sleep()
线程有什么区别?
我的理解是 wait()
-ing线程仍处于运行模式并使用CPU周期,但是sleep()
-ing不会消耗任何CPU周期吗?
我们为什么同时 拥有wait()
和sleep()
:它们的实现在较低的水平如何变化?
Answers:
A wait
可以被另一个notify
正在等待等待的监视器调用的线程“唤醒” sleep
。此外,wait
(和notify
)必须在synchronized
监视对象的块中发生,而sleep
不会:
Object mon = ...;
synchronized (mon) {
mon.wait();
}
此时,当前正在执行的线程将等待并释放监视器。另一个线程可能会做
synchronized (mon) { mon.notify(); }
(在同一mon
对象上),第一个线程(假设它是监视器上等待的唯一线程)将被唤醒。
您还可以notifyAll
在监视器上等待多个线程的情况下进行调用-这将唤醒所有线程。但是,只有一个线程将能够抓住显示器(记住,wait
是在synchronized
块中)并继续运行-然后其他被阻塞,直到它们获得监视器的锁为止。
另一点是,你叫wait
上Object
本身(即您等待对象的监视器上),而你打电话sleep
的Thread
。
另一个问题是,你可以得到虚假唤醒从wait
(即线程正在等待简历没有明显的原因)。在以下情况下,您应始终wait
旋转:
synchronized {
while (!condition) { mon.wait(); }
}
wait
/ notify
通常用于等待其他某个线程完成任务,或者等待直到满足特定条件。
没有提到的一个关键区别是,睡觉时一个线程并没有释放它持有,同时等待释放的对象的锁锁wait()
被称为上。
synchronized(LOCK) {
Thread.sleep(1000); // LOCK is held
}
synchronized(LOCK) {
LOCK.wait(); // LOCK is not held
}
sleep
持有Java锁,但事实并非如此。为了进行公平的比较,我们将与进行比较synchronized(OUTER_LOCK){ Thread.sleep(1000); }
,synchronized(OUTER_LOCK){ synchronized(LOCK){LOCK.wait();} }
我们可以看到两条指令都没有释放OUTER_LOCK
。如果有任何区别,我们可以说sleep
没有显式使用 Java锁,但是问题是询问报价“它们的实现在较低级别如何变化?” 取消报价。
wait()
在您的代码示例中,@Pacerier 与调用它的最内部锁定的条件相关联,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
我发现这篇文章很有帮助。它把之间的差异Thread.sleep()
,Thread.yield()
以及Object.wait()
对人类而言。报价:
最终,这一切都将归结到OS的调度程序,后者将时间片交给进程和线程。
sleep(n)
说:“我已经完成了时间片,请在至少n毫秒内不要再给我另一个时间片。” 在请求的时间过去之前,操作系统甚至不会尝试调度休眠线程。
yield()
说:“我已经完成了时间片,但还有很多工作要做。” 操作系统可以自由地立即给线程另一个时间片,或者给其他线程或处理CPU放弃的收益线程。
wait()
说:“我已经完成了时间片。在有人致电notify()之前,不要给我另一个时间片。” 与一样sleep()
,除非有人打电话notify()
(或发生其他一些唤醒情况之一),否则操作系统甚至不会尝试安排任务。当线程执行阻塞IO以及其他一些情况时,线程也会丢失其时间片的其余部分。如果线程在整个时间片中都正常工作,则操作系统将大致强制执行控制,就像
yield()
被调用一样,以便其他进程可以运行。您很少需要
yield()
,但是如果您有一个具有逻辑任务边界的繁重应用程序,则插入yield()
可能会改善系统响应能力(以时间为代价-上下文切换,甚至只是向OS和向后切换都是免费的)。一如既往地根据您关心的目标进行衡量和测试。
sleep(n)
隐式地说,当前正在运行的线程自动放弃了锁的监视器,这是不正确的。引用Thread的javadoc:“该线程不会失去任何监视器的所有权。”
sleep
与监视器相比,它没有任何其他与Java方法调用有关的特殊行为,也就是说,它不以任何方式进行交互或修改。如果要对监视器说些什么,则应指定wait
除上述内容外,还应暂时放弃对其调用的对象的锁定。
wait(n)
与进行比较sleep(n)
。比较使用no-arg没有意义。
这里有很多答案,但是我找不到任何提到的语义区别。
它与线程本身无关;这两种方法都是必需的,因为它们支持非常不同的用例。
sleep()
使线程像以前一样进入睡眠状态,它只是打包上下文并在预定的时间内停止执行。因此,为了在适当的时间之前将其唤醒,您需要了解线程引用。这在多线程环境中并不常见。它主要用于时间同步(例如,在3.5秒内准确唤醒)和/或硬编码的公平性(只需睡眠一会儿,然后让其他线程工作)。
wait()
相反,是一种线程(或消息)同步机制,该机制使您可以通知没有存储引用的线程(也不必担心)。您可以将其视为发布-订阅模式(wait
==订阅和notify()
==发布)。基本上,使用notify()可以发送一条消息(该消息甚至可能根本没有被接收到,通常您不在乎)。
综上所述,通常sleep()
用于时间同步和wait()
多线程同步。
它们可以在底层操作系统中以相同的方式实现,或者根本不实现(因为Java的早期版本没有真正的多线程;可能某些小型VM也不这样做)。不要忘记Java在VM上运行,因此您的代码将根据其运行的VM / OS / HW进行不同的转换。
在这里,我列出了wait()
和sleep()
方法之间的一些重要区别。
PS: 也单击链接以查看库代码(内部工作,请稍作练习以更好地理解)。
wait()
方法释放锁定。 wait()
是Object
上课的方法。wait()
是非静态方法- public final void wait() throws InterruptedException { //...}
wait()
应通过notify()
或notifyAll()
方法通知。wait()
需要从循环调用此方法以处理错误警报。
wait()
方法必须从同步上下文中调用(即,同步方法或块),否则它将抛出 IllegalMonitorStateException
sleep()
方法不会释放锁。sleep()
是java.lang.Thread
上课的方法。sleep()
是静态方法- public static void sleep(long millis, int nanos) throws InterruptedException { //... }
sleep()
完成。sleep()
最好不要从循环调用(即参见下面的代码)。sleep()
可以从任何地方调用。没有具体要求。参考:等待和睡眠之间的区别
调用等待和睡眠方法的代码片段
synchronized(monitor){
while(condition == true){
monitor.wait() //releases monitor lock
}
Thread.sleep(100); //puts current thread on Sleep
}
Thread.sleep()
用于使处理器时间可用于其他线程。睡眠期可以通过中断(即JVM)来终止。阅读本stackoverflow.com/questions/4264355/...
notify()
或notifyAll()
是Object
类方法。因此,它们是所有类的obj可用的(即这里也有Thread
类)。参见代码grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/…–
在等待和睡眠之后,我总结出一些不同的主要说明,首先使用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();
}
让我们澄清一些主要注意事项:
您通常使用sleep()进行时间同步,并使用wait()进行多线程同步。
如果我错了,请纠正我。
最根本的区别是,wait()
从Object
和sleep()
是一个静态方法Thread
。
主要区别在于,在等待wait()
期间sleep()
不释放任何锁定而释放锁定。
wait()
通常用于线程间通信,而sleep()
通常用于引入执行暂停。
wait()
应该从同步内部调用,否则我们会得到IllegalMonitorStateException
,而sleep()
可以在任何地方调用。
wait()
,您必须调用notify()
或notifyAll()
。至于sleep(),
线程是在指定的时间间隔后启动的。这是一个非常简单的问题,因为这两种方法的用法完全不同。
主要的区别是等待睡眠时不释放任何锁或监视器,而等待则释放锁或监视器。等待用于线程间通信,而睡眠用于引入执行暂停。
这只是一个清晰而基本的解释,如果您想要的更多,请继续阅读。
如果wait()
方法线程进入等待状态,并且在我们调用该notify()
方法之前,它不会自动返回(或者notifyAll()
如果有多个线程处于等待状态,并且您想唤醒所有这些线程)。并且您需要同步或对象锁或类锁来访问wait()
or 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()
将当前线程发送到“不可运行”状态(如)sleep()
,但要稍加调整。Wait是在对象而非线程上调用的;我们将此对象称为“锁定对象”。在lock.wait()
被调用之前,当前线程必须在锁对象上同步;wait()
然后释放该锁,并将线程添加到与该锁关联的“等待列表”。之后,另一个线程可以在同一个锁对象上进行同步并调用lock.notify()
。这将唤醒原始的等待线程。基本上,wait()
/notify()
类似于sleep()
/interrupt()
,只有活动线程不需要指向休眠线程的直接指针,而只需指向共享锁对象的指针。
等待和睡眠是两件事:
sleep()
线程中停止工作指定的持续时间。wait()
线程停止工作之前,通常由其他线程通知正在等待的对象。sleep
内停止运行,如果希望它停止直到某个输入来自其他线程,则可以使用wait
/ notify
。interrupt
旨在作为一种信号通知线程它应该停止执行正在执行的操作并终止。它由处理sleep
,wait
但也阻止了I / O函数(您可以通过调用method来实现具有相同行为的函数Thread.interrupted()
)。至于性能,通常会针对其设计目标对功能进行优化。
sleep()是一种用于将进程保留几秒钟或所需时间的方法,但是如果使用wait()方法,线程将进入等待状态,直到我们调用notify()或notifyAll()。
的主要区别是等待()释放锁或监视器,而睡眠()不释放任何锁或监视器,而等待。通常,“等待”用于线程间通信,而“睡眠”用于引入执行暂停。
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
}
让我们对以上所有点进行分类:
Call on:
Synchronized:
Hold lock:
Wake-up condition:
Usage:
简单来说,wait是等待,直到其他线程调用您,而sleep是在指定的时间段内“不执行下一条语句”。
此外,sleep是Thread类中的静态方法,它在线程上运行,而wait()在Object类中,并且在对象上调用。
还有一点,当您在某个对象上调用wait时,所涉及的线程将同步该对象,然后进行等待。:)
wait
和sleep
方法非常不同:
仔细想想,名字在这方面令人困惑;但是sleep
是标准名称,wait
类似于Win API中的WaitForSingleObject
或WaitForMultipleObjects
。
从这篇文章中: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()方法,线程不需要具有对象锁定。
睡眠/中断和等待/通知之间的一个潜在的大区别是
interrupt()
期间的调用sleep()
始终会引发异常(例如InterruptedException),而notify()
期间wait()
不打电话。在不需要时生成异常的效率很低。如果您的线程彼此之间的通信速度很高,那么如果您一直在调用中断,则会产生很多异常,这是对CPU的完全浪费。
您是正确的-Sleep()导致该线程“休眠”,并且CPU将会关闭并处理其他线程(否则称为上下文切换),我相信Wait会保持CPU处理当前线程。
两者兼有是因为虽然让您在不使用CPU时让其他人使用CPU似乎很明智,但实际上上下文切换会产生开销-根据睡眠时间长短,CPU周期可能会更昂贵切换线程要比简单地让您的线程在几毫秒内什么都不做更重要。
另请注意,睡眠会强制进行上下文切换。
另外-通常无法控制上下文切换-在“等待”期间,操作系统可能(并且将等待更长的时间)选择处理其他线程。
interrupt
。结束时间是n
在wait(n)
。¶¶已经八年了,仍然没有人能回答!
这些方法用于不同的事物。
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)
因此可以使用wait
to er,sleep
但是随后您就不得不打扰锁了。
在睡眠/等待时,这两种方法均未使用cpu。
这些方法是使用本机代码,使用类似的构造但不是以相同的方式实现的。
自己找:本机方法的源代码可用吗?该文件/src/share/vm/prims/jvm.cpp
是起点...
Thread.sleep(big_num)
必须被打断。Object.wait(small_num)
可以通知。
在这里wait()将一直处于等待状态,直到它被另一个线程通知为止,但是sleep()将会有一段时间..之后它将自动转移到Ready状态...
Wait()和sleep()的区别?
Thread.sleep()一旦完成工作,则仅将其释放给所有人。直到永远不会将锁释放给任何人。
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.
Object.wait()进入等待阶段时,将释放该键,并等待基于参数的几秒钟。
例如:
您用右手拿咖啡,也可以用同一只手拿另一个人,什么时候放下,然后只拿一个同类型的物体。也。这是sleep()你睡觉的时间你没有做任何工作,你只在睡觉。
等待()。当你放下心,在等待的时候再说一次,那就是等待
您正在播放电影或与您的播放器相同的系统中的任何内容,一次不能播放多个,这就是这里,当您关闭并选择另一首电影或歌曲时,这意味着等待
wait
释放锁而sleep
不会释放。处于等待状态的线程有资格在notify
或被notifyAll
调用时唤醒。但是在sleep
线程保持锁定的情况下,只有在睡眠时间结束后才有资格使用线程。
InterruptedException
Javadoc中所说的那样,将引发@Geek An 。
在我看来,这两种机制之间的主要区别在于,睡眠/中断是处理线程的最基本方法,而等待/通知是一种抽象,旨在简化线程之间的通信。这意味着睡眠/中断可以执行任何操作,但是此特定任务很难执行。
为什么等待/通知更合适?以下是一些个人注意事项:
它强制集中化。它允许协调具有单个共享库的一组线程之间的通信。这大大简化了工作。
它强制执行同步。因为这使程序员可以将调用包装在同步块中以等待/通知。
它与线程的来源和编号无关。使用这种方法,您可以任意添加更多线程,而无需编辑其他线程或跟踪现有线程。如果使用了睡眠/中断,则首先需要保留对睡眠线程的引用,然后手动逐个中断它们。
现实生活中的一个很好的例子可以解释这是一家经典餐厅以及员工之间进行交流的方法:服务员将客户的要求放在一个中央位置(软木板,桌子等),敲钟,厨房的工人来接了这样的要求。一旦准备好任何菜,厨房人员就会再次按铃,以使服务员意识到并把它们带给顾客。
关于睡眠的示例不会释放锁定,而等待会释放
这里有两个类:
Singleton:这是具有两个静态方法getInstance()和getInstance(boolean isWait)的Singleton类。
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();
}
}
和
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;
}
}
现在运行此示例,您将获得以下输出:
_instance :null
Both singleton are same
在这里,由threadA和threadB创建的Singleton实例是相同的。这意味着线程B正在外部等待,直到线程A释放它的锁为止。
现在,通过注释Thread.sleep(500)来更改Singleton.java;方法并取消注释Singleton.class.wait(500); 。这里是因为Singleton.class.wait(500); 方法threadA将释放所有获取锁,并进入“非可运行状态”,线程B将获得更改以进入同步块。
现在再次运行:
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
在这里,线程A和线程B创建的Singleton实例是不一样的,因为线程B更改为进入同步块,并且在500毫秒后,线程A从其最后一个位置开始,并创建了另一个Singleton对象。
应该从同步块中调用: wait()
方法总是从同步块中调用,即wait()
方法需要在调用对象监视器之前锁定对象监视器。但是sleep()
方法可以从外部同步块中调用,即sleep()
方法不需要任何对象监视器。
IllegalMonitorStateException:如果wait()
在未获取对象锁的情况下调用方法的情况与IllegalMonitorStateException
在运行时sleep()
引发的方法不同,但方法永远不会引发此类异常。
属于哪个类: wait()
方法属于java.lang.Object
类,但sleep()
方法属于java.lang.Thread
类。
在对象或线程上调用: wait()
方法在对象上调用,但sleep()
方法在线程上而不是对象上调用。
线程状态:当wait()
方法被调用的对象,跟帖说holded者对象的监视器从运行到待机状态去,并可以返回到可运行状态,只有当notify()
或notifyAll()
方法被调用该对象上。之后,线程调度程序会调度该线程从可运行状态变为运行状态。sleep()
在线程上调用when时,它将从运行状态变为等待状态,并且在睡眠时间到时可以返回到可运行状态。
从同步块调用时wait()
:调用方法时,线程将对象锁定。但是sleep()
,从同步块或方法线程中调用方法时,不会留下对象锁定。
更多参考
从oracle文档页面上的wait()方法Object
:
public final void wait()
notify()
的notifyAll()
方法。换句话说,此方法的行为就像完全执行call一样wait(0)
。该方法抛出
IllegalMonitorStateException
-如果当前线程不是对象监视器的所有者。
InterruptedException
-如果有任何线程在当前线程等待通知之前或期间中断了当前线程。引发此异常时,将清除当前线程的中断状态。
从oracle文档页面上关于类的sleep()方法的信息Thread
:
public static void sleep(long millis)
该方法抛出:
IllegalArgumentException
-如果Millis值为负
InterruptedException
-如果有任何线程中断了当前线程。引发此异常时,将清除当前线程的中断状态。
其他关键区别:
wait()
与静态方法sleep()
(类方法)不同,它是一种非静态方法(实例方法)。
wait()
在同步方法sleep()
内给出,而在非同步方法内给出,这是因为wait()
方法释放对象上的锁,sleep()
或者yield()
释放lock()
。
sleep()
可以在synchronized
块或方法内。答案什么也不能解释。
wait(1000)
使当前线程休眠一秒钟。
notify()
或notifyAll()
方法调用,则其睡眠时间可能少于1秒。sleep(1000)
导致当前线程休眠1秒。
sleep(1000)
不能保证准确地睡1秒钟。它可能之前被打断过。
实际上,所有这些在Java文档中都有清楚的描述(但是我只有在阅读了答案之后才意识到这一点)。
http://docs.oracle.com/javase/8/docs/api/index.html:
wait()-当前线程必须拥有此对象的监视器。线程释放此监视器的所有权,并等待直到另一个线程通过调用notify方法或notifyAll方法通知等待在此对象监视器上等待的线程唤醒。然后,线程等待,直到它可以重新获得监视器的所有权并恢复执行。
sleep()-根据系统计时器和调度程序的精度和准确性,使当前正在执行的线程进入休眠状态(暂时停止执行)达指定的毫秒数。该线程不会失去任何监视器的所有权。