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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 横溢天使 中级黑马   /  2015-9-26 13:10  /  5694 人查看  /  24 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

5黑马币
  1. class InputOutputDemo
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 Res r=new Res();
  6.                 Input i=new Input(r);
  7.                 Output o=new Output(r);
  8.                 Thread t=new Thread(i);
  9.                 Thread t1=new Thread(o);
  10.                 t.start();
  11.                 t1.start();
  12.         }
  13. }
  14. class Res
  15. {
  16.         String name;
  17.         String sex;
  18.         boolean flag;
  19. }
  20. class Input implements Runnable
  21. {
  22.         private Res r;
  23.         Input(Res r)
  24.         {
  25.                 this.r=r;
  26.         }
  27.         public void run()
  28.         {
  29.                 int x=0;
  30.                 while(true)
  31.                 {
  32.                         synchronized(r)
  33.                         {
  34.                                 if(!r.flag)
  35.                                         try{r.wait();}catch (Exception e){}
  36.                                 if(x==0)
  37.                                 {
  38.                                         r.name="Mike";
  39.                                         r.sex="man";
  40.                                 }
  41.                                 else
  42.                                 {
  43.                                         r.name="丽丽";
  44.                                         r.sex="女女";
  45.                                 }
  46.                                 x=(x+1)%2;
  47.                                 r.flag=false;
  48.                                 r.notify();

  49.                         }
  50.                 }
  51.         }
  52. }
  53. class Output implements Runnable
  54. {
  55.         private Res r;
  56.         Output(Res r)
  57.         {
  58.                 this.r=r;
  59.         }
  60.         public void run()
  61.         {
  62.                 while(true)
  63.                 {
  64.                         synchronized(r)
  65.                         {
  66.                                 if(!r.flag)
  67.                                         try{r.wait();}catch (Exception e){}
  68.                                 System.out.println(r.name+"*****"+r.sex);
  69.                                 r.flag=true;
  70.                                 r.notify();
  71.                         }
  72.                 }
  73.         }
  74. }
  75. 毕老师讲的flag这,我实在搞不懂。Input和Output里边的flag是一个吗?if(r.flag)是什么意思?是不是代表flag是true?可是我感觉默认的flag值是false啊!真心搞不懂,还请那位大神详细指点指点,我感激不尽
复制代码


24 个回复

倒序浏览
flag定义在成员位置,没有赋值,而boolean的默认值为false,所以flag是false,Input和Output都调用的是成员变量,另外!r.flag是取反,为true
回复 使用道具 举报
flag定义在成员位置,没有赋值,而boolean的默认值为false,所以flag是false,Input和Output都调用的是成员变量,另外!r.flag是取反,为true,如果我的回答对你有帮助,希望打赏几个黑马币,急需
回复 使用道具 举报
不好意思,我Input类里的if(r.flag),不是if(!r.flag),Output里边的是if(!r.flag),我上边打错了。。
我问的是Input类里的if(r.flag)。毕老师说if(r.flag)结果是true,我实在是想不明白,还请您详细解答下
回复 使用道具 举报
1.主函数下只声明了一个Res r,并将其分别传给了i和o,也就是说intput和output的中flag是同一个对象
2.if(r.flag)表示判断,如果r.flag==true,则继续执行该if作用域内的代码;如果r.flag==false,则跳过该if作用域内的代码,继续执行后续代码。
3.r.flag的值是不确定的,可能为true可能为false,只有当其为true时,if{}内的代码才会执行

点评

谢谢,问题解决  发表于 2015-9-27 22:54

评分

参与人数 1黑马币 +2 收起 理由
横溢天使 + 2 很给力!

查看全部评分

回复 使用道具 举报
15001162522 发表于 2015-9-26 17:21
1.主函数下只声明了一个Res r,并将其分别传给了i和o,也就是说intput和output的中flag是同一个对象
2.if(r. ...

为什么r.flag的值是不确定呢?flag默认值不是false吗?那自然r.flag的的值是false啊?就是这搞不懂
回复 使用道具 举报
a8336675 来自手机 中级黑马 2015-9-27 00:42:38
7#
楼主你还是要把问题描述清楚。看了几遍,代码倒是看明白了,却还没弄清楚你想问啥。。
回复 使用道具 举报
你的这个程序有点问题,你的程序会进入阻塞,可能你复制代码时出现了问题,其实这题考的是线程之间的通讯,也就是wait和notify。flag默认是false
回复 使用道具 举报
class InputOutputDemo
{
        public static void main(String[] args)
        {
                Res r=new Res();
                Input i=new Input(r);
                Output o=new Output(r);
                Thread t=new Thread(i);
                Thread t1=new Thread(o);
                t.start();
                t1.start();
        }
}
class Res
{
        String name;
        String sex;
        boolean flag;
}
class Input implements Runnable
{
        private Res r;
        Input(Res r)
        {
                this.r=r;
        }
        public void run()
        {
                int x=0;
                while(true)
                {
                        synchronized(r)
                        {
                                if(!r.flag)
                                        try{r.wait();}catch (Exception e){}
                                if(x==0)
                                {
                                        r.name="Mike";
                                        r.sex="man";
                                }
                                else
                                {
                                        r.name="丽丽";
                                        r.sex="女女";
                                }
                                x=(x+1)%2;
                                r.flag=false;
                                r.notify();

                        }
                }
        }
}
class Output implements Runnable
{
        private Res r;
        Output(Res r)
        {
                this.r=r;
        }
        public void run()
        {
                while(true)
                {
                        synchronized(r)
                        {
                                if(r.flag)
                                        try{r.wait();}catch (Exception e){}
                                System.out.println(r.name+"*****"+r.sex);
                                r.flag=true;
                                r.notify();
                        }
                }
        }
}
回复 使用道具 举报
正确代码
class InputOutputDemo
{
       public static void main(String[] args)
       {
               Res r=new Res();
               Input i=new Input(r);
               Output o=new Output(r);
              Thread t=new Thread(i);
               Thread t1=new Thread(o);
               t.start();
               t1.start();
       }
}
class Res
{
       String name;
       String sex;
       boolean flag;
}
class Input implements Runnable
{
       private Res r;
       Input(Res r)
       {
               this.r=r;
       }
       public void run()
       {
               int x=0;
               while(true)
               {
                       synchronized(r)
                       {
                               if(r.flag)
                                       try{r.wait();}catch (Exception e){}
                               if(x==0)
                               {
                                       r.name="Mike";
                                       r.sex="man";
                               }
                               else
                               {
                                       r.name="丽丽";
                                       r.sex="女女";
                               }
                               x=(x+1)%2;
                               r.flag=true;
                               r.notify();

                       }
               }
       }
}
class Output implements Runnable
{
       private Res r;
       Output(Res r)
       {
               this.r=r;
       }
       public void run()
       {
               while(true)
               {
                       synchronized(r)
                       {
                               if(!r.flag)
                                       try{r.wait();}catch (Exception e){}
                                                                try {
                                                                        Thread.sleep(1000);
                                                                } catch (InterruptedException e) {
                                                                 
                                                                        e.printStackTrace();
                                                                }
                               System.out.println(r.name+"*****"+r.sex);
                               r.flag=false;
                               r.notify();
                       }
               }
       }
}
回复 使用道具 举报
瑞雪雄起 发表于 2015-9-27 03:01
正确代码
class InputOutputDemo
{
  1.   if(r.flag)
  2.                                        try{r.wait();}catch (Exception e){}
  3.                                if(x==0)
  4.                                {
  5.                                        r.name="Mike";
  6.                                        r.sex="man";
  7.                                }
  8.                                else
  9.                                {
  10.                                        r.name="丽丽";
  11.                                        r.sex="女女";
  12.                                }
  13.                                x=(x+1)%2;
  14.                                r.flag=true;
  15.                                r.notify();
  16. 这段代码您能给解释下不?不明白什么意思,主要是开头if(r.flag)这不懂
复制代码
回复 使用道具 举报
Input 里的 if(!r.flag)  和  Output里if(r.flag)
这两个语句是对同一个flag进行判断,所以不管r.flag是true或false,都能保证一个if()判断为true,从而函数可以运行
事实上因为flag默认是false,所以是一开始是Input的run()先执行,input的run()方法末尾将r.flag设为ture,所以下次循环进来时,Input里面if()判断为false,不执行,而此时Output的if()判断true,output执行,末尾有改变flag,使下次循环时时Input执行,如此反复下去的。。。

其实flag相当于一个开关,它的作用是控制Input 和 Output交替执行任务(线程间通讯),flag为ture时,Input执行动作,Oupt不执行;flag为false时,相反。
而为了保证一个执行完后轮到另一个执行,在执行代码的末尾,就会将flag的值改变,相当于通知对方,我完成了,你可以运行了
回复 使用道具 举报
我也是新手,大概能明白你的问题在哪里,就是不知道能不能给你说明白
首先,你的问题应该是卡在这个唤醒机制的原理,也就是那个判断的原理,
我们从头来分析,这段代码运行的时候是随机运行的,有可能多存几次数据,在连续打印几个相同的数据,因为打印的就只有数据库里的那唯一一个数据,In是改变里面的数据,而out是打印里面的数据,在这个前提下,就必须要做到存一次,取一次,才能达到我们的目的
就是通过if判断flag来完成的,flag我们用文字来表示比较好理解,flag就假设他为数据库里有没有数据,true就是有,flase就是没有,flag初始化为false,假设是t1线程先运行,那么走out,会判断一下,发现(!flag)是真,即没有数据!于是t1开始wait,那就剩下t这个线程,走In这段代码,判断flag,发现没有数据,好,那就存进去数据,存完之后会把flag改为true,即表示已经有数据了,然后还顺手notify唤醒了刚才wait的out,但是唤醒了不一定就运行,也就是说,这个in还有可能在占有运行权,再走一遍,首先判断flag,发现是true,有数据了,不用存了,于是wait,这时候没有别的线程了,t1就开始了,判断flag,是真,有数据,于是打印,并把flag改成false,即表示数据已经取出了,没有数据了,然后再notify,把t线程再唤醒,。。。。。。。。大概就是这样的、、、不知道你能不能读得懂
回复 使用道具 举报

你把我的代码运行下,你就会发现打印的字符串交替运行,两个线程交替运行
回复 使用道具 举报
还在学基础,但是以后我会给你解决的.
回复 使用道具 举报
15001162522 发表于 2015-9-26 17:21
1.主函数下只声明了一个Res r,并将其分别传给了i和o,也就是说intput和output的中flag是同一个对象
2.if(r. ...

谢谢,问题解决了
回复 使用道具 举报
线程的同步问题。。。要充分考虑到申请资源和释放资源的问题。。。。因此要设置以各变量来控制。。。就叫做互斥信号量
回复 使用道具 举报
是同一个flag,因为flag是有无数据的依据。创建Res类时,boolean flag;此时flag默认是false,name和sex都没赋值,没有数据。r.flag中的r是创建Input或Output时作为参数传进来的对象r。当第一次进入Input中时,成员变量name和sex都没数据。r.flag == false,但!r.flag == true,就为成员变量赋值了。赋值后就是有数据了,flag就要flag = true了,为何你的代码没这样?
回复 使用道具 举报
liudongcan 发表于 2015-10-1 19:10
是同一个flag,因为flag是有无数据的依据。创建Res类时,boolean flag;此时flag默认是false,name和sex都 ...

你的代码有问题,没有数据都没赋值而是等待的
回复 使用道具 举报
不论是Input还是Output里的flag都引用的是r类中的flag,所以是一个。因为创建了r对象,所以会对flag进行初始化,而boolean类型的数据被初始化后的值为false,而if后的是(!r.flag这个值为true。
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马