转载:用实例揭示notify()和notifyAll()的本质区别 收藏

转载:用实例揭示notify()和notifyAll()的本质区别 收藏

转自:http://www.cnblogs.com/armyao/archive/2010/12/27/1917989.html
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/SuperMiner/archive/2007/04/22/1574615.aspx

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); // 需要5秒钟才能新产生一个Widget
                Widget w = new Widget();

                /*
                 * 
                 * 如果用notifyAll,则所有线程都企图冲出wait状态,第一个线程得到了锁,并取走了Widget,由于要间隔5秒针才new一个新的Widget,此时还没有新的Widget产生
                 * 并且解开了锁,然后第二个线程获得锁,运行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();

    }

}

这里写图片描述

总结一下:

notifyAll(),使线程退出wait状态,变成等待该对象上的锁
notify只选择一个wait状态线程进行通知,并使它获得该对象上的锁,其他等待线程继续处在wait状态

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值