Difference between wait() and sleep()
在线程中,
我是否理解
为什么我们同时拥有
一个
1 2 3 4 |
此时,当前正在执行的线程将等待并释放监视器。另一个线程可以
1 | synchronized (mon) { mon.notify(); } |
(在同一个
如果监视器上有多个线程在等待,您也可以调用
另一个观点是,你在
还有一点是,您可以从
1 2 3 | synchronized { while (!condition) { mon.wait(); } } |
一个尚未提到的关键区别是,当一个线程处于休眠状态时,它所持有的锁不会被释放,而等待会释放对
1 2 3 4 5 6 7 8 | synchronized(LOCK) { Thread.sleep(1000); // LOCK is held } synchronized(LOCK) { LOCK.wait(); // LOCK is not held } |
我发现这篇文章很有用。它把
It all eventually makes its way down to the OS’s scheduler, which
hands out timeslices to processes and threads.
sleep(n) says"I’m done with my timeslice, and please don’t give me
another one for at least n milliseconds." The OS doesn’t even try to
schedule the sleeping thread until requested time has passed.
yield() says"I’m done with my timeslice, but I still have work to
do." The OS is free to immediately give the thread another timeslice,
or to give some other thread or process the CPU the yielding thread
just gave up.
wait() says"I’m done with my timeslice. Don’t give me another
timeslice until someone calls notify()." As withsleep() , the OS won’t
even try to schedule your task unless someone callsnotify() (or one of
a few other wakeup scenarios occurs).Threads also lose the remainder of their timeslice when they perform
blocking IO and under a few other circumstances. If a thread works
through the entire timeslice, the OS forcibly takes control roughly as
ifyield() had been called, so that other processes can run.You rarely need
yield() , but if you have a compute-heavy app with
logical task boundaries, inserting ayield() might improve system
responsiveness (at the expense of time — context switches, even just
to the OS and back, aren’t free). Measure and test against goals you
care about, as always.
这里有很多答案,但我找不到任何提到的语义区别。
这与线程本身无关;这两种方法都是必需的,因为它们支持非常不同的用例。
相反,
综上所述,通常使用
它们可以以相同的方式在底层OS中实现,或者根本没有实现(因为以前版本的Java没有真正的多线程;可能一些小的VM也不这样做)。不要忘记Java在VM上运行,所以你的代码将根据它运行的VM/OS/HW来进行不同的转换。
这里,我列出了
为了处理虚警,需要从循环中调用
必须从同步上下文(即同步方法或块)调用
睡眠()
参考:等待和睡眠的区别
用于调用Wait and Sleep方法的代码段
1 2 3 4 5 6 7 | synchronized(monitor){ while(condition == true){ monitor.wait() //releases monitor lock } Thread.sleep(100); //puts current thread on Sleep } |
在处理wait和sleep之后,我总结了一些不同的关键注意事项,首先使用wait()和sleep()查看示例:
示例1:使用wait()和sleep():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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():对保存handObject对象的当前线程的调用
- sleep():调用线程execute task get beer(类方法会影响当前运行的线程)
- wait():当同步多线程访问同一对象(handObject)时(当需要多个线程之间的通信(thread execute coding,thread execute get beer)访问同一对象handObject)
- sleep():等待条件继续执行时(等待啤酒可用)
- wait():释放其他对象有机会执行的锁(handObject是空闲的,您可以执行其他任务)
- sleep():保持锁定至少T次(或直到中断)(我的工作仍然没有完成,我将继续保持锁定并等待某个条件继续)
- wait():直到调用notify(),notifyall()来自对象
- sleep():直到至少时间到期或调用中断
you normally use sleep() for time-syncronization and wait() for
multi-thread-synchronization.
如果我错了,请纠正我。
wait()和sleep()之间的差异
根本区别在于
wait() 来自Object ,sleep() 是Thread 的静态方法。主要区别在于,
wait() 释放锁,而sleep() 在等待时不释放任何锁。wait() 用于线程间通信,而sleep() 一般用于引入执行暂停。应该从内部同步调用
wait() ,否则我们得到IllegalMonitorStateException ,而sleep() 可以在任何地方调用。- 要从
wait() 重新启动线程,必须调用notify() 或notifyAll() 。对于sleep(), ,线程在指定的时间间隔后启动。
相似之处
- 两者都会使当前线程进入不可运行状态。
- 两者都是本地方法。
这是一个非常简单的问题,因为这两种方法的用途完全不同。
主要的区别是等待释放锁或监视器,而睡眠不释放任何锁或监视器,而等待。wait用于线程间通信,sleep用于引入执行暂停。
这只是一个清晰而基本的解释,如果你想要更多,那么继续阅读。
如果
但对于
还有一个更重要的区别,在采访中经常被问到:
这些都是
这两个方法之间有一个相似之处:它们都是被检查的语句,所以您需要尝试catch或throw来访问这些方法。
我希望这对你有帮助。
资料来源:http://www.jguru.com/faq/view.jsp?EID=47127
Thread.sleep() sends the current thread into the"Not Runnable" state
for some amount of time. The thread keeps the monitors it has aquired
-- i.e. if the thread is currently in a synchronized block or method no other thread can enter this block or method. If another thread callst.interrupt() it will wake up the sleeping thread.Note that sleep is a static method, which means that it always affects
the current thread (the one that is executing the sleep method). A
common mistake is to callt.sleep() where t is a different thread;
even then, it is the current thread that will sleep, not the t thread.
t.suspend() is deprecated. Using it is possible to halt a thread other
than the current thread. A suspended thread keeps all its monitors and
since this state is not interruptable it is deadlock prone.
object.wait() sends the current thread into the"Not Runnable" state,
likesleep() , but with a twist. Wait is called on an object, not a
thread; we call this object the"lock object." Beforelock.wait() is
called, the current thread must synchronize on the lock object;wait()
then releases this lock, and adds the thread to the"wait list"
associated with the lock. Later, another thread can synchronize on the
same lock object and calllock.notify() . This wakes up the original,
waiting thread. Basically,wait() /notify() is like
sleep() /interrupt() , only the active thread does not need a direct
pointer to the sleeping thread, but only to the shared lock object.
等待和睡眠是两件不同的事情:
- 在
sleep() 中,线程在指定的持续时间内停止工作。 - 在
wait() 中,线程停止工作,直到等待的对象被通知为止,通常是由其他线程通知的。
EDOCX1 0是一种EDCOX1×1的方法,EDCOX1×2是EDCOX1×3的一种方法,因此EDCOX1·4是一种在Java中使用监视器同步数据的技术,而EDCOX1·0是一种简单的线程暂停方法。
sleep()是一种方法,用于将进程保持几秒钟或您想要的时间,但如果wait()方法线程处于等待状态,则在调用notify()或notifyall()之前,它不会自动返回。
主要区别在于wait()释放锁或监视器,而sleep()在等待时不释放任何锁或监视器。wait用于线程间通信,而sleep通常用于在执行时引入暂停。
sleep()将当前线程发送到"不可运行"状态一段时间。线程保留它所获取的监视器-即如果线程当前位于同步块或方法中,则其他线程都不能进入此块或方法。如果另一个线程调用t.interrupt(),它将唤醒休眠线程。注意sleep是一个静态方法,这意味着它总是影响当前线程(执行sleep方法的线程)。一个常见的错误是调用t.sleep(),其中t是一个不同的线程;即使这样,它也是当前将休眠的线程,而不是t线程。
wait()将当前线程发送到"不可运行"状态,就像sleep()一样,但有一个扭曲。wait是对一个对象而不是线程调用的;我们称这个对象为"lock object"。在调用lock.wait()之前,当前线程必须在lock对象上同步;wait()然后释放这个锁,并将线程添加到与锁关联的"wait list"中。稍后,另一个线程可以在同一个锁对象上同步并调用lock.notify()。这会唤醒原始的等待线程。基本上,wait()/notify()类似于sleep()/interrupt(),只有活动线程不需要指向休眠线程的直接指针,而只需要指向共享锁对象。
1 2 3 4 5 6 7 | 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():直到至少时间到期或调用中断()。
- sleep():用于时间同步和;
- wait():用于多线程同步。
参考号:Diff
sleep 无法"唤醒",- 而
wait 在等待期间有一种"唤醒"的方式,通过另一个线程调用notify 或notifyAll 。
想一想,名称在这方面是混淆的,但是
从这篇文章: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()方法,线程不需要有对象锁。
简单地说,wait是等待直到其他线程调用您,而sleep是在指定的一段时间内"不执行下一条语句"。
此外,sleep是线程类中的静态方法,它在线程上操作,而wait()在对象类中并在对象上调用。
另一点是,当您在某个对象上调用wait时,线程会同步该对象,然后等待。:)
睡眠/中断和等待/通知之间的一个潜在的巨大区别是
- 在
sleep() 期间调用interrupt() 总是抛出一个异常(例如interruptedexception),而 - 在
wait() 期间打电话给notify() 没有。
在不需要时生成异常是低效的。如果线程之间的通信速率很高,那么如果您一直在调用interrupt,就会产生很多异常,这是对CPU的浪费。
您是正确的-sleep()导致该线程"休眠",CPU将关闭并处理其他线程(也称为上下文切换),而我认为wait使CPU处理当前线程。
我们两者都有,因为尽管让其他人在不使用CPU的情况下使用它似乎是明智的,但实际上,上下文切换有一个开销-取决于睡眠时间的长短,在CPU周期中切换线程可能比让线程在几毫秒内不做任何事情要贵得多。
还要注意,睡眠会强制上下文切换。
另外,一般来说,不可能控制上下文切换,在等待期间,操作系统可能(并且将等待更长的时间)选择处理其他线程。
这些方法用于不同的事情。
1 2 3 |
可以中断thread.sleep(n),但必须通知object.wait()。可以指定最长的等待时间:
两种方法都不会在休眠/等待时使用CPU。
这些方法是使用本机代码实现的,使用类似的构造,但方式不同。
寻找你自己:本地方法的源代码可用吗?文件
这里,wait()将处于等待状态,直到它被另一个线程通知,但是作为sleep()将有一段时间..之后,它将自动转移到就绪状态…
wait()和sleep()的区别?
线程()一旦它的工作完成,那么只有它向每个人释放锁。直到它永远不会向任何人释放锁。
1 | 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. |
WAITE()当它进入等待阶段时,它将根据参数释放密钥并等待一些秒。
例如:
你的右手拿着咖啡,你可以拿另一个同一只手的人,你什么时候放下,然后在这里只拿另一个同类型的东西。也。这是睡眠()你睡觉的时候没有工作,你只是在睡觉。这里也一样。
WAIT()当你被放下再拿一个时,意味着你在等待,那就是等待。
您正在播放电影或您的系统中的任何内容与播放机相同,您不能一次播放多个电影或歌曲,这就是这里,当您关闭并选择另一个时,任何人的电影或歌曲都意味着同时被称为等待。
从
1 | public final void wait() |
此方法引发
从
1 | public static void sleep(long millis) |
此方法引发:
其他主要区别:
在我看来,这两种机制的主要区别在于睡眠/中断是处理线程的最基本方式,而等待/通知是一种抽象,旨在使线程之间的通信更加容易。这意味着睡眠/中断可以做任何事情,但是这个特定的任务很难做。
为什么等待/通知更合适?以下是一些个人考虑事项:
它强制集中。它允许协调一组线程与单个共享对象之间的通信。这大大简化了工作。
它强制同步。因为它使程序员将等待/通知的调用包装在一个同步块中。
它独立于线程的起源和编号。使用这种方法,您可以任意添加更多线程,而无需编辑其他线程或跟踪现有线程。如果使用sleep/interrupt,首先需要保留对休眠线程的引用,然后手动逐个中断它们。
从现实生活中可以很好地解释这一点的一个例子是一家经典的餐厅和员工之间交流的方法:服务员把顾客的要求放在一个中心位置(软木板、桌子等),敲钟,厨房的工作人员来接受这样的要求。一旦有菜准备好了,厨房的工作人员就再按一下门铃,这样服务员就知道了,并把菜送到顾客那里。
关于睡眠不释放锁和等待的例子
这里有两个类:
singleton:这是singleton类,有两个静态方法getInstance()和getInstance(boolean iswait)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 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(); } } |
和
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | 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; } } |
现在运行这个示例,您将得到以下输出:
1 2 | _instance :null Both singleton are same |
这里,由threada和threadb创建的单例实例是相同的。这意味着苏莱达在外面等着苏莱达释放它的锁。
现在通过注释thread.sleep(500);方法并取消注释singleton.class.wait(500);来更改singleton.java。这里是因为singleton.class.wait(500);方法threada将释放所有的获取锁并进入"不可运行"状态,threadb将被更改为进入同步块。
现在再次运行:
1 2 3 4 5 6 7 8 | 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 |
这里,由threada和threadb创建的singleton实例是不同的,因为threadb在同步块中进行了更改,并且在500毫秒后,threada从其最后一个位置开始并创建了另一个singleton对象。
应该从synchronized块调用:
IllegalMonitorStateException:如果在不获取对象锁的情况下调用
属于哪个类:
在对象或线程上调用:对对象调用
线程状态:在对象上调用
当从synchronized块调用时:当调用
更多参考资料
同步方法中给出了
实际上,所有这些都是在Java文档中清楚地描述的(但是我在阅读了答案之后才意识到这一点)。
http://docs.oracle.com/javase/8/docs/api/index.html:
wait()-当前线程必须拥有此对象的监视器。线程释放此监视器的所有权,并等待另一个线程通知等待此对象监视器通过调用notify方法或notifyall方法。然后线程等待直到它可以重新获得监视器的所有权并继续执行。
sleep()-根据系统计时器和调度程序的精度和准确性,使当前执行的线程休眠(临时停止执行)指定的毫秒数。线程不会丢失任何监视器的所有权。
使用超时值等待可以在超时值结束时唤醒,或通知较早者(也可以是中断),而睡眠则在超时值结束时唤醒,或中断以较早者为准。不带超时值的wait()将一直等待,直到通知或中断为止。
- 方法
wait(1000) 使当前线程休眠一秒钟。- 如果线程接收到
notify() 或notifyAll() 方法调用,它可以休眠不到1秒。
- 如果线程接收到
- 对
sleep(1000) 的调用会使当前线程休眠1秒钟。- 另外,休眠线程不保存任何资源锁。但是等待线程是这样的。
假设你在听歌曲。
只要当前歌曲正在运行,下一首歌就不会播放,即sleep()由下一首歌调用
如果您完成了歌曲,它将停止播放,直到您选择播放按钮(notify())它将不播放,即等待()由当前歌曲调用。
在这两种情况下,歌曲将等待状态。