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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 关山明月 中级黑马   /  2015-2-2 20:28  /  1347 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 关山明月 于 2015-3-4 11:23 编辑

昨晚上看毕老师的视频,讲到同步、 wait() 和notify() 方法,具体代码如下:
  1. class Res   //资源
  2. {
  3.         private String name;
  4.         private String sex;
  5.         private boolean flag=false;
  6.         
  7.         public synchronized void set(String name,String sex)
  8.         {
  9.                 if(flag)
  10.                 {
  11.                         try{this.wait();} catch(Exception e){} //线程等待
  12.                 }
  13.                
  14.                         this.name=name;
  15.                         this.sex=sex;
  16.                         flag=true;
  17.                         this.notify();  //唤醒线程池中的在等待线程
  18.         }
  19.         public synchronized void out()
  20.         {
  21.                 if(!flag)
  22.                 {
  23.                         try{this.wait();} catch(Exception e){}    //线程等待
  24.                 }               
  25.                         System.out.println(this.name+"  "+this.sex);
  26.                         flag=false;
  27.                         this.notify();
  28.         }
  29.         
  30. }

  31. class Input implements Runnable   //输入线程
  32. {        
  33.         private Res r;
  34.         Input(Res r)
  35.         {
  36.                 this.r=r;
  37.         }
  38.         public void run()
  39.         {
  40.                 int x=0;
  41.                 while(true)
  42.                 {                                                                                
  43.                         if(x==0)
  44.                         {
  45.                                 r.set("张三","男");                                                
  46.                         }
  47.                         else
  48.                         {
  49.                                 r.set("lisi","woman");                                                               
  50.                         }
  51.                         x=(x+1)%2;                        
  52.                 }
  53.         }
  54. }

  55. class Output implements Runnable  //输出线程
  56. {
  57.         private Res r;
  58.         Output(Res r)
  59.         {
  60.                 this.r=r;
  61.         }
  62.         public void run()
  63.         {
  64.                 while(true)
  65.                 {
  66.                         r.out();
  67.                 }
  68.                
  69.         }
  70. }

  71. class MulThreadDemo2
  72. {
  73.         public static void main(String[] args)
  74.         {
  75.                 Res r=new Res();
  76.                
  77.                 new Thread(new Input(r)).start();
  78.                 new Thread(new Output(r)).start();                        
  79.         }
  80. }
复制代码
wait()是线程等待,notify()是唤醒线程池中的在等待线程,当第一次线程运行代码的时候,我自己创建的两个线程中另一个没有获得CUP执行权的线程就已经在线程池里处于等待状态吗?还没有接触到线程池,不知道自己创建的多个线程刚开始是什么状态的。。。。。如果刚开始不是在线程池里处于等待状态的话,那当第一个线程执行上面代码中的set()方法时,第一次运行notify()方法时唤醒的是哪个呢?

4 个回复

倒序浏览
唤醒的是在此对象监视器上等待的单个线程。,有一个notifyAll()则是唤醒全部进程。线程池,在方老师的深入JAVA课程中有讲过,你就当是一个数组,里面的数组元素都是一条条线程就好。notify唤醒线程后,线程是可执行的,但不一定运行,要等待CPU调用
回复 使用道具 举报
第一次线程运行是创建线程的时候,这个时候没有运行到wait,也就是说没有冻结状态。当时是有两个线程的一个是main,另一个就是新建立的线程,谁得到cpu执行权,谁继续运行,那么没有得到执行权的线程处于等待状态,注意不是冻结状态。这个时候两个线程会交替执行。当一个线程遇到wait的时候会进入冻结状态,之后必须使用notify来唤醒他还可以使其正常工作。当没有冻结线程的时候notify应该没有工作。以上我的理解。有不对的地方希望高手指教。
回复 使用道具 举报
本帖最后由 Ender亮 于 2015-2-3 08:54 编辑

代码中一共有三个线程:主线程,输入线程,输出线程。
主线程运行,会逐一开启二个线程,此时它们没有得到cpu运行权。主线程终止或cpu的原因,会让输入或输出线程得到cpu执行权。
如果是输入线程先得到CPU执行权,则最终会调用到07行的函数(并会循环这个函数),运行里面的代码:此时flag是flase,if语句不执行,继续向下,名字性别被赋值,flag被改为true;运行notify(),因为没有被wait()的线程,所以没有需要被唤醒的,然后在循环进入这个函数,此时flag为true,则这个线程调用wait()方法,睡眠了,释放了监视器(也就是视频中说的锁),等待被唤醒。
如果是输出线程先得到cpu执行权,同理,会最终调用19行的函数(并循环这个函数),运行里面代码:此时flag是flase,if语句执行,调用wait()方法,此线程被睡眠,释放了监视器(也就是视频中说的锁),等待被唤醒。

wait(),notify()方法是和对象相关联的,因为这个对象,所以他们联系到了一起,被放在了同一个线程池中(这个我自己的理解,我也不很清楚线程池,不用管线程池,只知道同一对象将他们联系到了一起就行),notify()会开启在线程池中的第一个由wait()睡眠的线程(先由wait()睡眠的就排前面),如果没有就不用开启。
回复 使用道具 举报 1 0
Ender亮 发表于 2015-2-3 08:46
代码中一共有三个线程:主线程,输入线程,输出线程。
主线程运行,会逐一开启二个线程,此时它们没有得到c ...

谢谢,标红色部分就是我需要的,弄明白了  :handshake
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马