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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 唐晓 中级黑马   /  2013-1-19 11:10  /  1185 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 唐晓 于 2013-1-19 11:11 编辑

需求:有20样东西,有拿走的,也有补货的。在货没有的时候,就不能拿走了,直到补货有了为止
class Res
{
        int thing=20;
}

class Input implements Runnable
{
        private Res r ;
        Input(Res r)
        {
                this.r = r;
        }
        public void run()
        {
               
                while(true)
                {
                        
                        synchronized(r)
                        {
                                System.out.println(Thread.currentThread().getName()+"...."+ r.thing++);
                                try{Thread.sleep(10);}
                                catch(Exception e){}
                        }
                        
                }
        }
}

class Output implements Runnable
{
        private Res r ;
        
        Output(Res r)
        {
                this.r = r;
        }
        public void run()
        {
                while(true)
                {
                        if(r.thing>0)
                        {
                        synchronized(r)
                        {                                
                                System.out.println(Thread.currentThread().getName()+"----"+r.thing--);        
                                try{Thread.sleep(10);}
                                catch(Exception e){}
                                
                        }
                }
                        }
        }
}


class  InputOutputDemo
{
        public static void main(String[] args)
        {
                Res r = new Res();

                Input in = new Input(r);
                Output out = new Output(r);
                Output out2 = new Output(r);
                Thread t1 = new Thread(in);
                Thread t2 = new Thread(out);
                Thread t3 = new Thread(out2);
                t1.start();
                t2.start();
                t3.start();
        }
}



运行代码如下:
Thread-0....20
Thread-0....21
Thread-0....22
Thread-0....23
Thread-1----24
Thread-1----23
Thread-2----22
Thread-2----21
Thread-2----20
Thread-1----19
Thread-1----18
Thread-1----17
Thread-0....16
Thread-0....17
Thread-0....18
Thread-1----19
Thread-1----18
Thread-2----17
Thread-1----16
Thread-1----15
Thread-1----14
Thread-1----13
Thread-1----12
Thread-1----11
Thread-0....10
Thread-0....11
Thread-0....12
Thread-0....13
Thread-0....14
Thread-0....15
Thread-1----16
Thread-1----15
Thread-1----14
Thread-1----13
Thread-1----12
Thread-2----11
Thread-2----10
Thread-2----9
Thread-1----8
Thread-1----7
Thread-1----6
Thread-1----5
Thread-1----4
Thread-1----3
Thread-0....2
Thread-0....3
Thread-0....4
Thread-0....5
Thread-0....6
Thread-0....7
Thread-0....8
Thread-0....9
Thread-0....10
Thread-0....11
Thread-1----12
Thread-1----11
Thread-1----10
Thread-1----9
Thread-1----8
Thread-1----7
Thread-1----6
Thread-1----5
Thread-2----4
Thread-2----3
Thread-2----2
Thread-2----1
Thread-1----0
Thread-0....-1
Thread-0....0
Thread-2----1
Thread-1----0
Thread-0....-1
Thread-0....0
怎么会出现-1了呢,取出的时候有判断了如果>0的时候才能--

评分

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

查看全部评分

3 个回复

倒序浏览
本帖最后由 黄金龙 于 2013-1-19 12:59 编辑
  1. class Res
  2. {
  3.         int thing=20;
  4. }

  5. class Input implements Runnable
  6. {
  7.         private Res r ;
  8.         Input(Res r)
  9.         {
  10.                 this.r = r;
  11.         }
  12.         public void run()
  13.         {
  14.                
  15.                 while(true)
  16.                 {
  17.                         
  18.                         synchronized(r)
  19.                         {
  20.                                 System.out.println(Thread.currentThread().getName()+"进货---------->"+ ++r.thing);//这里改成++r.thing
  21.                                 try{Thread.sleep(200);}
  22.                                 catch(Exception e){}
  23.                         }
  24.                         
  25.                 }
  26.         }
  27. }

  28. class Output implements Runnable
  29. {
  30.         private Res r ;
  31.         
  32.         Output(Res r)
  33.         {
  34.                 this.r = r;
  35.         }
  36.         public void run()
  37.         {
  38.                 while(true)
  39.                 {
  40.                         if(r.thing>0)//或者这里可以改成r.thing>1
  41.                         {
  42.                         synchronized(r)
  43.                         {                                
  44.                                 System.out.println(Thread.currentThread().getName()+"取货-----<"+ r.thing--);        
  45.                                 try{Thread.sleep(200);}
  46.                                 catch(Exception e){}
  47.                                 
  48.                         }
  49.                 }
  50.                         }
  51.         }
  52. }


  53. class  Demo08
  54. {
  55.         public static void main(String[] args)
  56.         {
  57.                 Res r = new Res();

  58.                 Input in = new Input(r);
  59.                 Output out = new Output(r);
  60.                 Output out2 = new Output(r);
  61.                 Thread t1 = new Thread(in);
  62.                 Thread t2 = new Thread(out);
  63.                 Thread t3 = new Thread(out2);
  64.                 t1.start();
  65.                 t2.start();
  66.                 t3.start();
  67.         }
  68. }


复制代码
你把sleep的值弄到200这样的就可以很直观看到问题出在什么地方了
问题出在r.thing++
这里打印的是上一个r.thing的数值...
改为++r.thing的时候就不会出现-1的情况
或者r.thing>1 也 可以解决问题

评分

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

查看全部评分

回复 使用道具 举报
好吧   表示刚好看出问题   楼上正解。
楼主可以设置下线程名称 如:
t1.setName("入+++");
t2.setName("OUT|||");
t3.setName("OUT|||");
验证发现出现-1的地方是输入线程。这样就看的非常清晰了。区别在++r.thing  和r.thing++上

评分

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

查看全部评分

回复 使用道具 举报
出现了多线程问题:
出现原因:多个线程操作了共享数据
解决办法:利用同步代码块或同步函数。
注意细节:就是判断改成while循环的形式,让它恢复了执行权就去判断一次。就不会出现安全问题了,
因为如果不加循环他会接着向下执行,这样就会出现安全问题了。

评分

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

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马