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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 赵太云 中级黑马   /  2013-7-15 15:46  /  1382 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 赵太云 于 2013-7-16 20:31 编辑

     为什么 wait()、notify()和notifyAll()方法只能在同步函数或同步代码块中使用?
  1. public class Test{
  2.         public static void main(String[] args){
  3.                 Resource resource = new Resource();
  4.                 Runnable r1 = new Input(resource);
  5.                 Runnable r2 = new Output(resource);
  6.                
  7.                 new Thread(r1).start();
  8.                 new Thread(r2).start();
  9.         }
  10. }

  11. class Resource{
  12.         public String name;
  13.         public String sex;
  14.         public boolean flag=false;
  15. }

  16. class Input implements Runnable{
  17.         private Resource resource;
  18.         public Input(Resource resource){
  19.                 this.resource = resource;
  20.         }
  21.         
  22.         public void run(){
  23.                 int x = 0;
  24.                 while (true){
  25.                         synchronized(resource){
  26.                                 if (resource.flag){
  27.                                         try{
  28.                                                 resource.wait();//这个为什么必须写在同步中?
  29.                                         }catch(Exception e){
  30.                                         }
  31.                                 }
  32.                                 if (0 == x){
  33.                                         resource.name = "mike";
  34.                                         resource.sex = "male";
  35.                                 }else {
  36.                                         resource.name = "丽丽";
  37.                                         resource.sex = "女";
  38.                                 }
  39.                                 x = (x+1)%2;
  40.                                 resource.flag = true;
  41.                                 resource.notify();//这个为什么必须写在同步中?
  42.                         }
  43.                 }
  44.         }
  45. }

  46. class Output implements Runnable {
  47.         private Resource resource;
  48.         
  49.         public Output(Resource resource){
  50.                 this.resource = resource;
  51.         }
  52.         
  53.         public void run(){
  54.                 while (true){
  55.                         synchronized(resource){
  56.                                 if (!resource.flag){
  57.                                         try{
  58.                                                 resource.wait();
  59.                                         }catch(Exception e){
  60.                                         }
  61.                                 }
  62.                                 System.out.println("name = " + resource.name + "  sex = " + resource.sex);
  63.                                 resource.flag = false;
  64.                                 resource.notify();
  65.                         }
  66.                 }
  67.         }
  68. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
神之梦 + 1 很给力!

查看全部评分

7 个回复

倒序浏览
因为wait notify notify 在使用的时候需要一个监视器对象就是锁   
在API文档中有说明   
回复 使用道具 举报
a767175432 发表于 2013-7-15 17:02
因为wait notify notify 在使用的时候需要一个监视器对象就是锁   
在API文档中有说明     ...

为什么要这样设计呢?
回复 使用道具 举报
a767175432 发表于 2013-7-15 17:02
因为wait notify notify 在使用的时候需要一个监视器对象就是锁   
在API文档中有说明     ...

为什么要这样设计呢?
回复 使用道具 举报
a767175432 发表于 2013-7-15 17:02
因为wait notify notify 在使用的时候需要一个监视器对象就是锁   
在API文档中有说明     ...

为什么要这样设计呢?
回复 使用道具 举报
赵太云 发表于 2013-7-15 17:11
为什么要这样设计呢?

加入多个线程都操作统一资源 这一资源加上一把锁  
设1 2.....n个线程来操作
如果一个线程遇到了wait等待了
另一个线程用notify()来唤醒等待的线程  
假如没有锁 那么那个线程就不知道唤醒哪个线程了。

或者一个线程在A锁上挂起,另一个线程持有B锁,那么他只能唤醒B锁上挂起的线程,不会唤醒A锁上挂起的线程

这就是要这么设计

评分

参与人数 1技术分 +1 收起 理由
神之梦 + 1 赞一个!

查看全部评分

回复 使用道具 举报
当前的线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,直到其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得对监视器的所有权后才能继续执行。

对于某一个参数的版本,实现中断和虚假唤醒是可能的,而且此方法应始终在循环中使用:
  1. synchronized (obj) {
  2. while (<condition does not hold>)
  3. obj.wait();
  4. ... // Perform action appropriate to condition
  5.      }
复制代码
此方法只应由作为此对象监视器的所有者的线程来调用

注意最后一句: 此方法只应由作为此对象监视器的所有者的线程来调用。如果不给当前对象加锁,你无法拥有当前对象。

评分

参与人数 1技术分 +1 收起 理由
神之梦 + 1 赞一个!

查看全部评分

回复 使用道具 举报
闲人忙啊 发表于 2013-7-15 18:08
当前的线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,直到其他线程通过调用 notify 方法 ...

该线程发布对此监视器的所有权并等待??
  wait()方法不是释放了锁的吗?
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马