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

}

}

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/SuperMiner/archive/2007/04/22/1574615.aspx

转载于:https://www.cnblogs.com/w-wfy/p/5893270.html

用实例揭示notify()和notifyAll()的本质区别相关推荐

  1. notify()和notifyAll()的本质区别

    notify()和notifyAll()的本质区别 notify()和notifyAll()都是Object对象用于通知处在等待该对象的线程的方法.两者的最大区别在于: notifyAll使所有原来在 ...

  2. notify() 和 notifyAll() 有什么区别?

    notify() 和 notifyAll() 有什么区别? 先解释两个概念. 等待池:假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁后,进入到了该对象的等待池,等待池中的线程 ...

  3. Object的notify和notifyAll方法的区别

    区别 notify:只会唤醒等待该锁的其中一个线程. notifyAll:唤醒等待该锁的所有线程. 既然notify会唤醒一个线程,并获取锁,notifyAll会唤醒所有线程并根据算法选取其中一个线程 ...

  4. Java并发编程—notify和notifyAll有什么区别?

    原文作者:知乎用户 原文地址:https://www.zhihu.com/question/37601861/answer/145545371 著作权归作者所有.商业转载请联系作者获得授权,非商业转载 ...

  5. java中的notify和notifyAll有什么区别?

    作者:知乎用户 链接:https://www.zhihu.com/question/37601861/answer/145545371 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业 ...

  6. notify()和notifyAll()有什么区别?

    notify() 和 notifyAll() 都是 Object 对象用于通知处在等待该对象的线程的方法. void notify(): 唤醒一个正在等待该对象的线程. void notifyAll( ...

  7. notify()和 notifyAll()有什么区别

    notify()和notifyAll()的区别? notify(): 唤醒一个处于等待状态的线程, 注意的是在调用此方法的时候, 并不能确切的唤醒某一个等待状态的线程, 而是由JVM确定唤醒哪个线程, ...

  8. notify()和 notifyAll()有什么区别?

    在Java中,notify()和notifyAll()都可以用于线程的唤醒,但它们有以下几个区别: 1. 唤醒数量不同 notify()方法只会随机唤醒等待队列中的一个线程,而notifyAll()方 ...

  9. Java 中 notify 和 notifyAll 有什么区别?

    notify() 方法不能唤醒某个具体的线程,所以只有一个线程在等待的时候它才有 用武之地.而 notifyAll()唤醒所有线程并允许他们争夺锁确保了至少有一个线程 能继续运行.

最新文章

  1. python3网络编程实战
  2. 乔布斯诞辰67周年,他的这些思想仍值得我们学习
  3. 文巾解题 8. 字符串转换整数 (atoi)
  4. 广东省老龄化预测及影响因素分析
  5. Boost.PolyCollection 性能测试
  6. Project Chameleon Work In Progress 11
  7. [(转)hystar整理]Entity Framework 教程
  8. 【Java】分享一个诡异的可见性问题
  9. Hadoop生态圈-Flume的组件之sink处理器
  10. Eclipse的tomcat出现:the server cannot started because one or more of the ports are invalid
  11. springSecurity 基于方法权限控制@RolesAllowed @Serured @PreAuthorize 与 页面端标签控制权限...
  12. (转载)oracle10g在win10上的安装
  13. Java十大常用框架介绍
  14. verilog实现状态机
  15. 实现python源代码加密
  16. hadoop fs,hadoop dfs以及hdfs dfs区别
  17. simulink常用模块
  18. 多功能音频工具的旗舰音乐编辑工具!Music Studio
  19. 2个硬盘离线导致raid崩溃的数据恢复案例
  20. 创意svg+css3相册图文展示

热门文章

  1. Java 多线程概述
  2. Docker 入门系列(2)- Docker 镜像, 免 sudo 使用 docker 命令、获取查看、修改镜像标签、查找删除创建镜像、导入导出镜像
  3. 通过python利用哈希值实现比较两个文件的一致性
  4. npm run dev 报错:missing script:dev
  5. LeetCode简单题之检查是否所有字符出现次数相同
  6. TensorFlow常用Python扩展包
  7. Linux下Flash-LED的处理
  8. 如何在TVM上集成Codegen(下)
  9. 传感器融合带来多重好处
  10. java is not a enclosing class_Java Class getEnclosingClass()用法及代码示例