打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
用实例揭示notify()和notifyAll()的本质区别

notify()和notifyAll()都是Object对象用于通知处在等待该对象的线程的方法。两者的最大区别在于:

notifyAll使所有原来在该对象上等待被notify的线程统统退出wait的状态,变成等待该对象上的,一旦该对象被解锁,他们就会去竞争。
notify则文明得多他只是选择一个wait状态线程进行通知,并使它获得该对象上的锁,但不惊动其他同样在等待被该对象notify的线程们,当第一个线程运行完毕以后释放对象上的锁此时如果该对象没有再次使用notify语句,则即便该对象已经空闲,其他wait状态等待的线程由于没有得到该对象的通知,继续处在wait状态,直到这个对象发出一个notify或notifyAll,它们等待的是被notify或notifyAll,而不是锁。

下面是一个很好的例子:

import java.util.*;

class Widget{}
class WidgetMaker extends Thread{
    List
<Widget> finishedWidgets=new ArrayList<Widget>();
    
public void run(){
        
try{
            
while(true){
                Thread.sleep(
5000);//act busy
                Widget w=new Widget();
                
//也就是说需要5秒钟才能新产生一个Widget,
这决定了一定要用notify而不是notifyAll
                
//因为上面两行代码不是同步的,如果用notifyAll则所有线程都企图冲出wait状态
                
//第一个线程得到了锁,并取走了Widget(这个过程的时间小于5秒,新的Widget还没有生成)
                
//并且解开了锁,然后第二个线程获得锁(因为用了notifyAll其他线程不再等待notify语句
                
//,而是等待finishedWidgets上的锁,一旦锁放开了,他们就会竞争运行),运行
                
//finishedWidgets.remove(0),但是由于finishedWidgets现在还是空的,
                
//于是产生异常
                
//***********这就是为什么下面的那一句不能用notifyAll而是要用notify
                                
                
synchronized(finishedWidgets){
                    finishedWidgets.add(w);
                    finishedWidgets.notify(); 
//这里只能是notify而不能是notifyAll
                }

            }

        }

        
catch(InterruptedException e){}
    }

    
    
public Widget waitForWidget(){
        
synchronized(finishedWidgets){
            
if(finishedWidgets.size()==0){
                
try{
                    finishedWidgets.wait();
                }

                
catch(InterruptedException e)
                
{}
            }

            
return finishedWidgets.remove(0);
        }

    }

}

public class WidgetUser extends Thread{
    
private WidgetMaker maker;
    
public WidgetUser(String name,WidgetMaker maker){
        
super(name);
        
this.maker=maker;
    }

    
public void run(){
        Widget w
=maker.waitForWidget();
        System.out.println(getName()
+"got a widget");
    }

    

    
public static void main(String[] args) {
        WidgetMaker maker
=new WidgetMaker();
        maker.start();
        
new WidgetUser("Lenny",maker).start();
        
new WidgetUser("Moe",maker).start();
        
new WidgetUser("Curly",maker).start();

    }


}

 



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1574615

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Java之线程初步II
为什么wait()、notify()方法需要和synchronized一起使用
sleep()和wait()有什么区别
java线程概述 -- JR 精品文章
Java多线程设计模式详解之二
Android:线程的结束,挂起和恢复(下)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服