专注收集记录技术开发学习笔记、技术难点、解决方案
网站信息搜索 >> 请输入关键词:
您当前的位置: 首页 > 行业应用

用范例揭示notify()和notifyAll()的本质区别

发布时间:2010-06-06 18:50:28 文章来源:www.iduyao.cn 采编人员:星星草
用实例揭示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 finishedWidgets=new ArrayList();

    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();

    }

}


友情提示:
信息收集于互联网,如果您发现错误或造成侵权,请及时通知本站更正或删除,具体联系方式见页面底部联系我们,谢谢。

其他相似内容:

  • 《松本行弘的程序全世界》之面向对象

    《松本行弘的程序世界》之面向对象 最近读《SICP》把脑细胞搞死大半,还没看完2章,而且看得也是一知半解,实在是受不了了,...

  • GroovyHelp 3.2.7 GA公布

    GroovyHelp 3.2.7 GA发布 GroovyHelp简介   GroovyHelp是一款Javadoc及Groovydoc搜索查阅软件,它能够帮助Java开发人员以...

  • Velocity在Roller中的使用

    Velocity在Roller中的应用 Velocity是java世界中出现比较早,也比较成熟的、性能比较好的、应用也比较广泛的模板框架。   所...

  • Rpc远程调用框架的设计与兑现(2)

    Rpc远程调用框架的设计与实现(2) 接上: 3   基于Json的前后端数据交互 3.1   轻量级的数据交换形式 3.1.1    什么是Jso...

  • excel 单元格的锁定 以及 JXL的兑现方式

    excel 单元格的锁定 以及 JXL的实现方式 在使用excel表格时,有些列是不希望用户可以修改的,诸如审计日志里面确定的部分,而审计...

  • 仓秤跟散料秤:java连接opc Server

    仓秤和散料秤:java连接opc Server 这三篇都是之前写好的,一直没发。 这次一起发出来吧。   java连接硬件很痛苦,特别是对我这...

  • Rpc远程调用框架的设计与兑现(1)

    Rpc远程调用框架的设计与实现(1) Rpc远程调用框架的设计与实现 1     Rpc远程调用框架设计概述 1.1   研究背景 1.1.1...

  • 集合中的线程安全有关问题

    集合中的线程安全问题 一、why? Java中常用的集合框架推荐使用的三个实现:HashSet\ArrayList\HashMap都是线程不安全的.如...

  • Java定时任务的兑现

    Java定时任务的实现 本例依据Java自身提供的接口实现,通过监听器(Listener)和定时器(Timer)定时执行某个任务(Task)。 MyListener: ...

  • java中log日记的使用

    java中log日志的使用 一、介绍  Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控...

热门推荐: