`
buzhucele
  • 浏览: 331301 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

用实例揭示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();

    }

}
分享到:
评论

相关推荐

    Java多线程实例图形版

    wait()、notify()和notifyAll()方法用于线程间的通信,使得线程可以等待特定条件满足后再继续执行;还有volatile关键字保证了多线程环境下的可见性和有序性,避免了线程缓存造成的数据不一致。 在这个实例中,我们...

    哲学家就餐多线程实例图形版

    Java作为一门广泛应用于并发编程的语言,提供了丰富的工具和机制来解决此类问题,如synchronized关键字、wait()、notify()和notifyAll()方法等。在"哲学家就餐多线程实例图形版"的压缩包中,包含了使用Java实现的这...

    2013年java笔试题大集合及答案

    2. 同步机制,如synchronized关键字、wait()、notify()和notifyAll()的用法。 3. 线程池的概念,为什么要使用ExecutorService? 七、JVM与内存管理 理解JVM是优化Java程序的关键,可能的考点: 1. JVM内存区域...

    java并发编程实践

    同时,作者也讨论了线程间的通信,如wait()、notify()和notifyAll()方法,以及使用它们进行复杂条件等待的技巧。 除了理论知识,本书还涵盖了实战经验,比如如何进行性能调优,如何避免并发陷阱,以及如何诊断和...

    Java 2 核心技术 第一卷源码

    6. **多线程编程**:Java提供了强大的多线程支持,源码将展示如何创建和管理线程,理解线程同步机制(如synchronized关键字、wait()、notify()和notifyAll()方法),以及死锁和活锁的概念。 7. **反射与动态代理**...

    多线程的运用

    5. 线程通信:使用wait(), notify(), notifyAll()方法可以在特定条件下控制线程间的协作,或者使用BlockingQueue等高级并发工具。 在“ThreadTest”这个文件中,可能包含了实现多线程的示例代码,可以用来实践和...

    JAVA基础面试大全.doc corejavanetbook.doc jsp技术大全.pdf

    标题中的三个文件名揭示了Java基础、核心Java和JSP技术相关的知识点,这些是Java开发者在面试准备中经常关注的领域。以下是对这些主题的详细解释: 1. **Java基础面试大全.doc**: 这个文档可能包含了Java语言的基础...

    Java简单程序(多线程的应用)

    线程间的同步和通信可能通过`synchronized`关键字、`wait()`, `notify()`或`notifyAll()`方法来实现,以防止数据竞争和确保结果的正确性。 程序可能会包含以下几个关键组件: - **线程类**:为每个物理运动创建一...

    JAVA考试题目

    这些文档标题揭示了它们是关于Java程序设计的考试题目和答案,主要针对的是期末考试,且涉及了不同级别的学生群体,如2004级和计算机06级。以下是基于这些资源可能涵盖的Java编程相关知识点的详细说明: 1. **Java...

    Java解惑PPT8

    解决这类问题通常需要理解Java内存模型和线程同步机制,例如`synchronized`关键字、`wait()`, `notify()`和`notifyAll()`方法的使用。 **Puzzle 78 反射的污染** 这个谜题揭示了Java访问控制的边界。即使`hashCode...

    Java开发笔试题.docx

    Java中实现线程同步的方法有synchronized关键字、wait()、notify()和notifyAll(),以及Lock接口(如ReentrantLock)。 7. **JSP/Servlet中的forward()与redirect()** - forward()是服务器内部重定向,请求被转发到...

    Java经典试题及答案

    - **wait**:不仅会让线程暂停,还会释放锁,直到其他线程调用`notify`或`notifyAll`方法唤醒。 #### 十一、错误与异常 - **Error**:表示系统级的错误,一般无法恢复,如`OutOfMemoryError`。 - **Exception**:...

    Java Object类详解_动力节点Java学院整理

    9. `wait(), notify(), notifyAll()`: 这些方法涉及线程同步,允许一个线程等待其他线程释放资源(通过调用notify()或notifyAll())。它们必须在synchronized块或方法中使用,否则会抛出...

    multithreading:基本的多线程java网络

    Java提供了多种机制来解决这个问题,如wait(), notify()和notifyAll()方法,它们用于线程间的同步。这些方法必须在synchronized块或方法中使用,因为它们涉及到对对象监视器的管理。此外,还可以使用Java的并发工具...

    -Java-Concurrency-in-Practice-Source-Code:在以下代码中使用的所有源代码(也许) ,包括我编写的用于下载这些文件的python程序-java source download

    源码中可能包含对线程的创建、生命周期管理以及同步机制如`synchronized`关键字、`wait()`, `notify()`和`notifyAll()`方法的实例。 2. **并发工具类**:Java提供了一些高级并发工具,如`ExecutorService`, `Future...

    pacman:在一个简单的吃豆游戏中使用了高级多线程编程。 在本示例中,您将了解多线程概念是多么简单,因为您了解了一个有趣的娱乐游戏内部究竟发生了什么

    此外,合理地使用`wait()`, `notify()`和`notifyAll()`方法可以协调线程间的交互。 在"Pacman-master"压缩包中,源代码很可能包含各个线程的实现,如游戏主循环、幽灵移动逻辑、碰撞检测等模块。通过分析这些代码,...

    PROJ207_Team6:项目工作坊 – CMPP264 Java 主题

    `Runnable`接口的使用更为灵活,因为它可以与任何实现了该接口的对象一起使用,而不仅仅是`Thread`类的实例。`Thread`类的子类化则可以直接重写`run()`方法,但可能会遇到单继承的限制。 线程的管理包括启动线程...

Global site tag (gtag.js) - Google Analytics