A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 秦冲 黑马帝   /  2012-5-29 00:39  /  2269 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

notify,notifyAll,wait等关于线程的方法为什么设计在了object类里?

6 个回复

倒序浏览
Java Monitor 从两个方面来支持线程之间的同步,即:互斥执行与协作。 Java 使用对象锁 ( 使用 synchronized 获得对象锁 ) 保证工作在共享的数据集上的线程互斥执行 , 使用 notify/notifyAll/wait 方法来协同不同线程之间的工作。这些方法在 Object 类上被定义,会被所有的 Java 对象自动继承。
实质上,Java 的 Object 类本身就是监视者对象,Java 语言对于这样一个典型并发设计模式做了内建的支持。不过,在 Java 里,我们已经看不到了我们在 C++ 一节所讨论的区域锁与条件变量的概念。下图很好地描述了 Java Monitor 的工作机理。

线程如果获得监视锁成功,将成为该监视者对象的拥有者。在任一时刻内,监视者对象只属于一个活动线程 (Owner) 。拥有者线程可以调用 wait 方法自动释放监视锁,进入等待状态。
1. wait() 方法:
要调用一个对象的wait()方法,只有当前线程获取了这个对象的锁,换句话说一定要在这个对象的同步方法或以这个对象为参数的同步块中.当一个线程调用了wait() 方法后,这个线程就进入了这个对象的休息室(waitset),这是一个虚拟的对象,但JVM中一定存在这样的一个数据结构用来记录当前对象中有哪些程线程在等待。然后它就会释放锁,让其它线程来获取这个锁.
这个线程只能等待其它线程调用notity[All]来唤醒.
但是如果调用的是有参数的wait(time)方法,则线程会在休息室中等待这个时间后自动唤醒.
class Test{
    public synchornized void test(){
      //获取条件,int x 要求大于100;
      while(x < 100)  // 注意这里是while 每次被唤醒后,还是要检查条件是否满足
        wait();
      perform();  // 执行操作
    }
}
2. notify() notifyAll() 方法:
这两个方法都是把某个对象上休息区内的线程唤醒,notify只能唤醒一个,但究竟是哪一个不能确定,而notifyAll则唤醒这个对象上的休息室中所有的线程.
一般为了保险起见,我们在绝对多数时候应该使用notifiAll(),除非你明确知道只唤醒其中的一个线程.

评分

参与人数 1技术分 +1 收起 理由
攻城狮 + 1 赞一个!

查看全部评分

回复 使用道具 举报
简单点说吧,因为notify,notifyAll,wait这几个方法是要用到锁的,也就是说是锁的方法,锁可以是任意类型的,所以为了能让这几个方法通用,就定义在了所有类的最高父类,Object中,因为所有的类都继承额它,保证了所有的锁都能用!!它定义在Object中就因为一个锁,没其他的~~

评分

参与人数 1技术分 +1 收起 理由
攻城狮 + 1 赞一个!

查看全部评分

回复 使用道具 举报
因为这些方法在操作同步线程时,都必须要标识它们所操作线程持有的锁,只有同一个锁上的被等待线程,才可以被同一个锁上的notify唤醒,不可以对不同锁中的线程进行唤醒
也就是说,等待和唤醒必须是同一个锁。而锁可以是任意对象,所以可以被任意对象调用的方法 就定义在Object类中
回复 使用道具 举报
         因为每个对象都有一把锁,不仅仅是Thread对象,      

      你说的这些方法都使用在锁中,因为要对持有锁的线程操作,
      
      每一个对象都是一个锁,所以将这些操作锁的方法 定义在了超类当中      
      
回复 使用道具 举报
  1. 当前线程必须拥有此对象监视器.该线程发布对此监视器的所有权并等待,直到其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来.然后该线程将等到重新获得对监视器的所有权后才能继续执行.
复制代码
上面这段话是API中对wait()方法的使用原则的说明,意思是你操作同步中的线程时,必须要标识其操作线程所使用的锁(监视器),只有所属同一个锁的被wait()的线程才可以被所属同一个锁的notify()/notifyAll()唤醒,所属不同的锁的线程间是不可以进行等待唤醒操作的,等待与唤醒使用的是同一把锁,锁可以是任意对象,可以被任意对象调用的方法是可以定义在Object类中的.
回复 使用道具 举报
有两点原因:
1.wait notify notifyAll方法都必须使用在同步代码块中,它们必须依赖于监视器,就是我们说的锁对象
2.任何对象都可以是监视器,因为任何对象都从Object类继承所以这些方法写到Object类是比较合适的
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马