`
kanwoerzi
  • 浏览: 1644692 次
文章分类
社区版块
存档分类
最新评论

线程中的wait和notify方法

 
阅读更多
wait()notify()notifyall()方法是java.lang.Object类为线程提供的用于实现线程间通信的同步控制方法<wbr style="line-height:25px">。</wbr>
wait()方法使当前线程主动释放互斥锁,并进入该互斥锁的等待队列。(也就是说,它使当前线程暂停执行,
等待其他线程执行<wbr style="line-height:25px"><span style="color:#ff9900; line-height:25px">notify()</span>方法或者<span style="color:#ff9900; line-height:25px">notifyall()</span><wbr style="line-height:25px">方法后再继续执行本线程。)<br style="line-height:25px"></wbr></wbr>
notify()系列方法,用于释放一个项目的线程,唤醒另一个可能在等待的线程。
线程等待有两种调用格式:
<wbr style="line-height:25px"><span style="color:#000080; line-height:25px">1</span><span style="color:#ff00ff; line-height:25px">.wait()</span><span style="color:#000080; line-height:25px">等待通信线程唤醒后再继续执行本线程。<br style="line-height:25px"> 2.</span><span style="color:#ff00ff; line-height:25px">wait(longmillis)</span><wbr style="line-height:25px"><span style="color:#000080; line-height:25px">等待通信线程唤醒或者最多等待</span><span style="color:#99cc00; line-height:25px">millis</span><span style="color:#000080; line-height:25px">毫秒后,再继续执行本线程。</span></wbr></wbr>

调用wait()notify()系列方法时,当前线程必须拥有此对象监视器(即对象锁)。如果当前线程不是此对象监视器的所有者,会抛IllegalMonitorStateException<wbr style="line-height:25px">。</wbr>
通过以下三种方法之一,线程可以成为对象监视器的所有者:
<wbr style="line-height:25px"><span style="color:#000080; line-height:25px">*通过执行此对象的同步实例方法。<br style="line-height:25px"> *通过执行在此对象上进行同步的synchronized语句的正文。<br style="line-height:25px"> *对于Class类型的对象,可以通过执行该类的同步静态方法<wbr style="line-height:25px">。</wbr></span><br style="line-height:25px"><span style="line-height:25px">注意1</span>:对于一个对象,某一时刻只能有一个线程拥有该对象的监视器。<wbr style="line-height:25px"><br style="line-height:25px"><span style="color:#993300; line-height:25px">publicfinalvoid</span><span style="color:#ff6600; line-height:25px">wait()</span><br style="line-height:25px"> throwsInterruptedException<br style="line-height:25px"> 在其他线程调用此对象的notify()方法或notifyAll()方法前,导致当前线程等待。换句话说,此方法的行为就好像它仅执行wait(0)调用一样。<br style="line-height:25px"> 当前线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,直到其他线程通过调用notify方法,<br style="line-height:25px"> 或notifyAll方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得对监视器的所有权后才能继续执行。<br style="line-height:25px"> 对于某一个参数的版本,实现中断和虚假唤醒是可能的,而且此方法应始终在循环中使用:<br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#ff6600; line-height:25px">synchronized</span><span style="color:#3366ff; line-height:25px">(obj){<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">while</span><span style="color:#3366ff; line-height:25px">(&lt;conditiondoesnothold&gt;)<br style="line-height:25px"> obj.wait();<br style="line-height:25px"> .</span><span style="color:#808080; line-height:25px">..//Performactionappropriatetocondition</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"> 此方法只应由作为此对象监视器的所有者的线程来调用。<br style="line-height:25px"> 抛出:<br style="line-height:25px"> IllegalMonitorStateException-如果当前线程不是此对象监视器的所有者。<br style="line-height:25px"> InterruptedException-如果在当前线程等待通知之前或者正在等待通知时,任何线程中断了当前线程。<br style="line-height:25px"> 在抛出此异常时,当前线程的中断状态被清除。<br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">注意1</wbr></span><wbr style="line-height:25px">:wait()方法后,当前线程暂停执行,线程进入Blocked状态,<span style="line-height:25px"><wbr style="line-height:25px">cpu不会分给其时间</wbr></span><wbr style="line-height:25px">,<br style="line-height:25px"> 等待其他线程执行notify()方法或者notifyall()方法或用interrupt()取消后再继续执行本线程<br style="line-height:25px"> 它还有种调用格式:<br style="line-height:25px"> wait(longmillis)等待通信线程唤醒或者最多等待millis毫秒后,再继续执行本线程。<br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">注意2</wbr></span><wbr style="line-height:25px">:wait()方法使当前线程主动<wbr style="line-height:25px"><span style="color:#000080; line-height:25px">释放互斥锁</span><wbr style="line-height:25px">.<br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">注意3</wbr></span><wbr style="line-height:25px">:线程A调用了wait()进入了等待状态,也可以用<span style="line-height:25px"><wbr style="line-height:25px">interrupt()取消</wbr></span><wbr style="line-height:25px">.详细参考《线程的interrupt》<br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">注意4</wbr></span><wbr style="line-height:25px">:对于某一个参数的版本,实现中断和虚假唤醒是可能的,而且此方法应始终在循环中使用。<br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">publicfinalvoidnotify()</wbr></span><wbr style="line-height:25px"><br style="line-height:25px"> 唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。<br style="line-height:25px"> 选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个wait方法,在对象的监视器上等待。<br style="line-height:25px"> 直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争;<br style="line-height:25px"> 例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。<br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">注意1</wbr></span><wbr style="line-height:25px">:被notify()唤醒的线程,也只有在<span style="line-height:25px"><wbr style="line-height:25px">当前线程放弃此对象上的锁定后</wbr></span><wbr style="line-height:25px">,才可能<span style="line-height:25px"><wbr style="line-height:25px">被执行</wbr></span><wbr style="line-height:25px">,<br style="line-height:25px"> (他需要以常规方式与在该对象上主动同步的其他所有线程进行锁竞争,竞争成功了还能被执行)<br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">publicfinalvoidnotifyAll()</wbr></span><wbr style="line-height:25px"><br style="line-height:25px"> 唤醒在此对象监视器上等待的所有线程。线程通过调用其中一个wait方法,在对象的监视器上等待。<br style="line-height:25px"> 直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争;<br style="line-height:25px"> 例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。<br style="line-height:25px"> 此方法只应由作为此对象监视器的所有者的线程来调用。<br style="line-height:25px"> 抛出:<br style="line-height:25px"> IllegalMonitorStateException-如果当前线程不是此对象监视器的所有者。<br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">注意1</wbr></span><wbr style="line-height:25px">:被唤醒的线程,也只有在当前线程放弃此对象上的锁定后,才可能被执行,<br style="line-height:25px"> (他需要以常规方式与在该对象上主动同步的其他所有线程进行锁竞争,竞争成功了还能被执行)<br style="line-height:25px"> wait(),notify(),notifyall()所在对象和锁是绑定的(他们是一一对应的,即一个锁只对应对象,一个对象只对应锁)。<br style="line-height:25px"> 因此它的wait(),notify(),notifyall()都是操作同一个对象。<br style="line-height:25px"> 但是我们只想通过notify(),notifyall()来对一些wait()线程而不是该锁上所有wait()的线程进行唤醒时。(这样的效率要高很多,当然应该不只是可以得到效率的好处)<br style="line-height:25px"> synchronized和wait(),notify(),notifyall()就显得苍白无力。<br style="line-height:25px"> 幸好java1.5中提供了ReentrantLock,ReadLock,WriteLock来和Condition配套使用以实现这种功能。<br style="line-height:25px"><span style="line-height:25px">示例1</span><br style="line-height:25px"><span style="color:#993300; line-height:25px">class</span><span style="color:#3366ff; line-height:25px">BoundedBuffer{</span><br style="line-height:25px"><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">finalString[]items=newString[100];</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">intputptr,takeptr,count;</span><br style="line-height:25px"><span style="color:#0000ff; line-height:25px">finalStringconditionPut="put";<br style="line-height:25px"> finalStringconditionTake="take";</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">synchronizedpublicvoid</span><span style="color:#3366ff; line-height:25px"></span><span style="color:#ff6600; line-height:25px">put</span><span style="color:#3366ff; line-height:25px">(Stringx)throwsInterruptedException{<br style="line-height:25px"> while(count==items.length)<br style="line-height:25px"> {<br style="line-height:25px"> System.out.println("Itisfull.theactionofputiswait");<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">synchronized</span><span style="color:#3366ff; line-height:25px">(conditionPut)<br style="line-height:25px"> {<br style="line-height:25px"> conditionPut.wait();</span><span style="color:#808080; line-height:25px">//@1</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">items[putptr]=x;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">if(++putptr==items.length)putptr=0;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">++count;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">synchronized</span><span style="color:#3366ff; line-height:25px">(conditionTake)<br style="line-height:25px"> {<br style="line-height:25px"> conditionTake.notify();<br style="line-height:25px"> }<br style="line-height:25px"> }<br style="line-height:25px"><br style="line-height:25px"></span><span style="color:#993300; line-height:25px">synchronizedpublic</span><span style="color:#3366ff; line-height:25px">String</span><span style="color:#ff6600; line-height:25px">take()</span><span style="color:#3366ff; line-height:25px">throwsInterruptedException{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">while</span><span style="color:#3366ff; line-height:25px">(count==0)</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">System.out.println("Itisempty.theactionoftakeiswait");</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">synchronized</span><span style="color:#3366ff; line-height:25px">(conditionTake)</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">conditionTake.wait();</span><span style="color:#808080; line-height:25px">//@1</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">Stringx=items[takeptr];</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">if</span><span style="color:#3366ff; line-height:25px">(++takeptr==items.length)takeptr=0;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">--count;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">synchronized</span><span style="color:#3366ff; line-height:25px">(conditionPut)</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">conditionPut.notify();</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">returnx;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">注意</wbr></span><wbr style="line-height:25px">:在<span style="color:#808080; line-height:25px">@1</span>处无法进行当前线程对this的锁的释放,当然别的线程也就无法进入put和take,<br style="line-height:25px"> 线程就死锁了。<br style="line-height:25px"> 实例1:<br style="line-height:25px"> 因为<span style="color:#ff6600; line-height:25px">wait()</span>,<span style="color:#ff6600; line-height:25px">notify()</span>,<span style="color:#ff6600; line-height:25px">notifyall()</span>所在对象和锁是绑定的<br style="line-height:25px"> notify(),notifyall()是对对象(锁)上所有wait()的线程进行唤醒(notify是随机选一个)。<br style="line-height:25px"> 所以只能用下面的方式。<br style="line-height:25px"><span style="color:#993300; line-height:25px">class</span><span style="color:#3366ff; line-height:25px"></span><span style="color:#ff6600; line-height:25px">BoundedBuffer</span><span style="color:#3366ff; line-height:25px">{<br style="line-height:25px"> finalString[]items=newString[100];<br style="line-height:25px"> intputptr,takeptr,count;<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">synchronizedpublicvoid</span><span style="color:#3366ff; line-height:25px">put(Stringx)throwsInterruptedException{<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">while</span><span style="color:#3366ff; line-height:25px">(count==items.length)</span><span style="color:#808080; line-height:25px">@5</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">System.out.println("Itisfull.theactionofputiswait");</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">this.wait();</span><span style="color:#808080; line-height:25px">//@1</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">items[putptr]=x;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">if(++putptr==items.length)</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">putptr=0;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">++count;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">this.notify();</span><span style="color:#808080; line-height:25px">@2</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">synchronizedpubli</span><span style="color:#3366ff; line-height:25px">cString</span><span style="color:#ff6600; line-height:25px">take()</span><span style="color:#3366ff; line-height:25px">throwsInterruptedException{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">while</span><span style="color:#3366ff; line-height:25px">(count==0)</span><span style="color:#808080; line-height:25px">//@6</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">System.out.println("Itisempty.theactionoftakeiswait");</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">this.wait();</span><span style="color:#808080; line-height:25px">//@3</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">Stringx=items[takeptr];</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">if</span><span style="color:#3366ff; line-height:25px">(++takeptr==items.length)</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">{</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">takeptr=0;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">--count;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">this.notify();</span><span style="color:#808080; line-height:25px">//@4</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">returnx;</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="color:#3366ff; line-height:25px">}</span><br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">注意</wbr></span><wbr style="line-height:25px">:<span style="color:#000080; line-height:25px">虽然我们希望的是@1处由@4出来唤醒,@3处由@2出来唤醒。</span><br style="line-height:25px"><span style="color:#000080; line-height:25px">但是</span><span style="color:#99cc00; line-height:25px">notify()</span><span style="color:#000080; line-height:25px">,</span><span style="color:#808000; line-height:25px">notifyall()</span><span style="color:#000080; line-height:25px">是对锁上所有</span><span style="color:#339966; line-height:25px">wait()</span><span style="color:#000080; line-height:25px">的线程进行唤醒(notify是随机选一个)。</span><br style="line-height:25px"><span style="color:#000080; line-height:25px">因此</span><span style="color:#808080; line-height:25px">@2</span><span style="color:#000080; line-height:25px">出也可能唤醒</span><span style="color:#808080; line-height:25px">@1</span><span style="color:#000080; line-height:25px">,所以</span><span style="color:#999999; line-height:25px">@5</span><span style="color:#000080; line-height:25px">出要用</span><span style="color:#0000ff; line-height:25px">while</span><span style="color:#000080; line-height:25px">来判断是否真的满足条件了,</span><span style="color:#808080; line-height:25px">@6</span><span style="color:#000080; line-height:25px">同理。</span></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics