Java中的Object的Wait() 和notify()方法使用时应注意的地方和Thread中的sleep()方法

Java中的Object的Wait() 和notify()方法使用时应注意的地方和Thread中的sleep()方法

2013年03月24日  ⁄ 综合 ⁄ 共 2115字 ⁄ 字号  小 中 大  ⁄ 评论关闭
id="cproIframe_u1788635_2" width="336" height="280" src="http://pos.baidu.com/acom?adn=3&at=231&aurl=&cad=1&ccd=24&cec=UTF-8&cfv=17&ch=0&col=zh-CN&conBW=0&conOP=1&cpa=1&dai=2&dis=0&ltr=http%3A%2F%2Fwww.baidu.com%2Fs%3Fwd%3DJava%25E4%25B8%25AD%25E7%259A%2584Object%25E7%259A%2584Wait()%2520%25E5%2592%258Cnotify()%25E6%2596%25B9%25E6%25B3%2595%25E4%25BD%25BF%25E7%2594%25A8%25E6%2597%25B6%25E5%25BA%2594%25E6%25B3%25A8%25E6%2584%258F%25E7%259A%2584%25E5%259C%25B0%25E6%2596%25B9%25E5%2592%258CThread%25E4%25B8%25AD%25E7%259A%2584sleep()%25E6%2596%25B9%25E6%25B3%2595%26rsv_bp%3D0%26ch%3D%26bar%3D%26rsv_spt%3D3%26tn%3DSE_hldp01010_6r0gix1f&ltu=http%3A%2F%2Fwww.xuebuyuan.com%2F1658925.html&lu_161=0&lunum=6&n=83099053_cpr&pcs=1920x955&pis=10000x10000&ps=326x1186&psr=1920x1080&pss=1920x346&qn=54bf11f96aff74c0&rad=&rsi0=336&rsi1=280&rsi5=4&rss0=%23FFFFFF&rss1=%23FFFFFF&rss2=%230000ff&rss3=%23444444&rss4=%23008000&rss5=&rss6=%23e10900&rss7=&scale=&skin=tabcloud_skin_3&stid=5&td_id=1788635&titFF=%E5%AE%8B%E4%BD%93&titFS=12&titTA=left&tn=text_default_336_280&tpr=1432719256460&ts=1&version=2.0&xuanting=0&dtm=BAIDU_DUP2_SETJSONADSLOT&dc=2&di=u1788635&ti=Java%E4%B8%AD%E7%9A%84Object%E7%9A%84Wait()%20%E5%92%8Cnotify()%E6%96%B9%E6%B3%95%E4%BD%BF%E7%94%A8%E6%97%B6%E5%BA%94%E6%B3%A8%E6%84%8F%E7%9A%84%E5%9C%B0%E6%96%B9%E5%92%8CThread%E4%B8%AD%E7%9A%84sleep()%E6%96%B9%E6%B3%95%20%7C&tt=1432719256447.126.228.229" align="center,center" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" allowtransparency="true" style="margin: 0px; padding: 0px; border-width: 0px; border-style: initial; background: transparent;">

1)sleep 是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep 不会释放对象锁。
wait 是Object 类的方法,对此对象调用wait 方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify 方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。

1、这两个方法来自不同的类分别是Thread和Object
2、最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
3、wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用(使用范围)

<ol class="linenums" style="margin: 0px; padding: 0px 0px 0px 10px; border: none; list-style-position: outside; background: transparent;"><li class="L0" style="color: rgb(153, 153, 153); list-style-type: decimal; list-style-position: initial; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; background-color: rgb(250, 250, 250);"><span class="kwd" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 139); font-weight: bold; background: transparent;">synchronized</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 0); background: transparent;">(</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 0); background: transparent;">x</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 0); background: transparent;">){</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 0); background: transparent;"></span>
</li><li class="L1" style="color: rgb(153, 153, 153); list-style-type: decimal; list-style-position: initial; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; background-color: rgb(250, 250, 250);"><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 0); background: transparent;">  x</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 0); background: transparent;">.</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 0); background: transparent;">notify</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 0); background: transparent;">()</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 0); background: transparent;"></span>
</li><li class="L2" style="list-style-type: decimal; list-style-position: initial; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; background-color: rgb(250, 250, 250);"><span style="margin: 0px; padding: 0px; border: 0px; color: rgb(255, 0, 0); background: transparent;"><span class="pln" style="margin: 0px; padding: 0px; border: 0px; background: transparent;">  </span><span class="com" style="margin: 0px; padding: 0px; border: 0px; background: transparent;">//或者wait()</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; background: transparent;"></span>
</span></li><li class="L3" style="color: rgb(153, 153, 153); list-style-type: decimal; list-style-position: initial; margin: 0px; padding: 0px 0px 0px 10px; border: none; line-height: 20px; background-color: rgb(250, 250, 250);"><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 0); background: transparent;">  </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 0); background: transparent;">}</span></li></ol>

4、sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常

sleep方法属于Thread类中方法,表示让一个线程进入睡眠状态,等待一定的时间之后,自动醒来进入到可运行状态,不会马上进入运行状态,因为线程调度机制恢复线程的运行也需要时间,一个线程对象调用了sleep方法之后,并不会释放他所持有的所有对象锁,所以也就不会影响其他进程对象的运行。但在sleep的过程中过程中有可能被其他对象调用它的interrupt(),产生InterruptedException异常,如果你的程序不捕获这个异常,线程就会异常终止,进入TERMINATED状态,如果你的程序捕获了这个异常,那么程序就会继续执行catch语句块(可能还有finally语句块)以及以后的代码

注意sleep()方法是一个静态方法,也就是说他只对当前对象有效,例如t是一个线程,通过指定t.sleep()让t对象进入sleep,这样的做法是错误的,它只会是使当前线程被sleep 而不是t线程

wait属于Object的成员方法,一旦一个对象调用了wait方法,必须要采用notify()和notifyAll()方法唤醒该进程;如果线程拥有某个或某些对象的同步锁,那么在调用了wait()后,这个线程就会释放它持有的所有同步资源,而不限于这个被调用了wait()方法的对象。wait()方法也同样会在wait的过程中有可能被其他对象调用interrupt()方法而产生

2)Wait()和notify():如果条件不满足,则等待。当条件满足时,等待该条件的线程将被唤醒。一般用在synchronized机制中。

例如:线程A

   synchronized(obj) {

               while(!condition) {

                         obj.wait();

                 }

                obj.doSomething();

.....

  }

当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait()。在另一线程B中,如果B更改了某些条件,使得线程A的condition条件满足了,就可以唤醒线程A。

线程B

      synchronized(obj) {

              condition = true;

              obj.notify();

        }

需要注意的概念是:  

   1.调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj) {……} 代码段内(或synchronized方法中)。  

   2.调用obj.wait()后,线程A就释放了obj的锁,否则线程B无法获得obj锁,也就无法在synchronized(obj) {……} 代码段内唤醒A.  

   3.当obj.wait()方法返回后,线程A需要再次获得obj锁,才能继续执行。  

   4.如果A1,A2,A3都obj.wait(),则B调用obj.notify()只能唤醒A1,A2,A3中的一个(具体哪一个由JVM决定)。  

   5.obj.notifyAll()则能全部唤醒A1,A2,A3,但是要继续执行obj.wait()的下一条语句,必须获得obj锁,因此,A1,A2,A3只有一个有机会获得锁继续执行,例如A1,其余的需要等待A1释放obj锁之后才能继续执行。

   6.当B调用obj.notify/notifyAll的时候,B正持有obj锁,因此,A1,A2,A3虽被唤醒,但是仍无法获得obj锁。直到B退出synchronized块,释放obj锁后,A1,A2,A3中的一个才有机会获得锁继续执行。

3)为什么wait(),notify()方法要和synchronized一起使用?

因为wait()方法是通知当前线程等待并释放对象锁,notify()方法是通知等待此对象锁的线程重新获得对象锁,然而,如果没有获得对象锁,wait方法和notify方法都是没有意义的,即必须先获得对象锁,才能对对象锁进行操作,于是,才必须把notify和wait方法写到synchronized方法或是synchronized代码块中了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值