黑马程序员技术交流社区

标题: 多线程问题,究竟哪儿错了 [打印本页]

作者: 小石头39910    时间: 2013-5-28 14:25
标题: 多线程问题,究竟哪儿错了
本帖最后由 小石头39910 于 2013-5-29 08:58 编辑

它一直说43行的notify()错误
class Rec
{
         String name;
         String sex;
         boolean flag=false;
        public void get()
        {
           this.name=name;
           this.sex=sex;
        }
}
class Input implements Runnable
{
        private Rec r;
        Input(Rec r)
        {
        this.r=r;
作者: 杨聂    时间: 2013-5-28 16:21
我觉得应该用r来调用notify()方法吧,锁定什么对象就用什么对象来执行notify()。
作者: 张洪慊    时间: 2013-5-28 16:44
本帖最后由 张洪慊 于 2013-5-28 16:47 编辑

妹纸 (*^__^*) 嘻嘻……  我要占楼~~
运行你的代码报了一个没留意过的异常:
IllegalMonitorStateException - 如果当前线程不是此对象监视器的所有者(这句话给了我提示)
  1.   synchronized(r)//这里使用锁r,也就是new Rec()锁
  2.                   {
  3.                         if(r.flag)
  4.                           {
  5.                             try{r.wait();}catch(Exception e){}//这里需要指示wait()的线程所持有的锁
  6.                           }
  7.                            if(x==0)
  8.                             {
  9.                  r.name="mike";
  10.                          r.sex="man";
  11.                             }
  12.                             else
  13.                             {
  14.                  r.name="傻蛋";
  15.                           r.sex="女";
  16.                             }
  17.                              x=(x+1)%2;//为了间隔,对二求余
  18.                              r.flag=true;//把flag值设为ture
  19. notify();
  20. //r.notify();//修正后
  21.                         /*
  22.                         这个位置报错,这句话相当于this.notify(即使加上还是该错误)
  23.                        也就是this锁并不是该线程的所有者,因为这里没有给出this锁.
  24.                        
  25.                        */
  26.                     }
  27.         

  28.                 }
  29.          
  30.         }
复制代码
第二个线程的run方法同时用到了同步代码块和同步函数,在这里用不到,可以选用同时都是同步函数/同步代码块
和上面对应把你代码修正下,使用同步代码块:
  1.   public void run()
  2.         {
  3.                 while(true)
  4.                 {
  5.                         
  6.                        synchronized(r)//是不是用的同一个锁
  7.                       {
  8.                        if(r.flag)//r.flag=true说明有值需要打印
  9.                         {
  10.                           System.out.println(r.name+"-------"+r.sex);
  11.                         }
  12.                          r.flag=false;
  13.                                                  r.notify();
  14.                                                  try{r.wait();}catch(Exception e){}//打印完之后唤醒输入->进入等待
  15.                                                  /*
  16.                                                  这段程序怎么写都行,逻辑正确就OK
  17.                                                 
  18.                                                  */
  19.                       }
  20.         }
  21.       }
复制代码
最后关于:IllegalMonitorStateException(API),RuntimeException子类
抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程。
->说的太拗口了
理解了下:
①某一线程已经试图等待锁
② 以上面为例:
    该线程notify其他正在等待锁(this)
    而该线程自身没有该锁(this)



作者: 逸盏清茶    时间: 2013-5-28 16:49
public void get()
        {
           this.name=name;
           this.sex=sex;
        }



你这里要接收两个参数吧,不然怎么赋值
作者: 小石头39910    时间: 2013-5-29 10:26
张洪慊 发表于 2013-5-28 16:44
妹纸 (*^__^*) 嘻嘻……  我要占楼~~
运行你的代码报了一个没留意过的异常:
IllegalMonitorStateException  ...

我改了一下但是运行第二次的时候好像死活唤不醒输入的run了

只能运行这一个
作者: 张洪慊    时间: 2013-5-29 12:18
小石头39910 发表于 2013-5-29 10:26
我改了一下但是运行第二次的时候好像死活唤不醒输入的run了

只能运行这一个 ...

  1. class Rec
  2. {
  3.          String name;
  4.          String sex;
  5.          boolean flag=false;
  6.         public void get()
  7.         {
  8.            this.name=name;
  9.            this.sex=sex;
  10.         }
  11. }
  12. class Input implements Runnable
  13. {
  14.         private Rec r;
  15.         Input(Rec r)
  16.         {
  17.         this.r=r;
  18.         }
  19.         public void run()
  20.         {
  21.                         int x=0;
  22.             while(true)
  23.                  {
  24.                    synchronized(r)//加同步锁
  25.                   {
  26.                         if(r.flag)//判断flag如果为true就等待否则就传值
  27.                           {
  28.                             try{r.wait();}catch(Exception e){}
  29.                           }
  30.                            if(x==0)
  31.                             {
  32.                          r.name="mike";
  33.                          r.sex="man";
  34.                             }
  35.                             else
  36.                             {
  37.                          r.name="傻蛋";
  38.                           r.sex="女";
  39.                             }
  40.                              x=(x+1)%2;//为了间隔,对二求余
  41.                         r.flag=true;//把flag值设为ture
  42.                         r.notify();//唤醒输出线程
  43.                     }
  44.         

  45.                 }
  46.          
  47.         }
  48. }
  49. class Output implements Runnable
  50. {
  51.         //Object obj=new Object();
  52.         private Rec r;
  53.         Output(Rec r)
  54.         {
  55.           this.r=r;
  56.         }
  57.         public void run()
  58.         {   
  59.                 while(true)
  60.                 {
  61.                         
  62.                        synchronized(r)//是不是用的同一个锁
  63.                       {/*
  64.                        if(r.flag)//r.flag=true说明有值需要打印
  65.                         {
  66.                           System.out.println(r.name+"-------"+r.sex);
  67.                         }
  68.                          r.flag=false;
  69.                                                  r.notify();
  70.                                                  try{r.wait();}catch(Exception e){}//打印完之后唤醒输入->进入等待
  71.                                                 */
  72.                                            if(!r.flag)
  73.                                                   try{r.wait();}catch(Exception e){}
  74.                                            System.out.println(r.name+"-------"+r.sex);
  75.                                            r.flag=false;
  76.                                            r.notify();
  77.                                            /*以上两种写法任选一种,均测试过*/
  78.                       }
  79.         }
  80.       }
  81. }
  82. class  InputOutDemo
  83. {
  84.         public static void main(String[] args)
  85.         {
  86.             Rec c=new Rec();
  87.            Input in=new Input(c);
  88.            Output ou=new Output(c);

  89.                 Thread t1=new Thread(in);//定义线程
  90.                 Thread t2=new Thread(ou);
  91.                 t1.start();
  92.                 t2.start();
  93.         }
  94. }

复制代码

作者: 小石头39910    时间: 2013-5-29 16:17
张洪慊 发表于 2013-5-29 12:18

thank you simida
作者: 张洪慊    时间: 2013-5-29 17:30
小石头39910 发表于 2013-5-29 16:17
thank you simida

妹纸威武,妹纸加油~~吼~~~~




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2