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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 张扬123 于 2012-8-7 21:11 编辑
  1. class ProducerConsumerDemo
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 Resource r = new Resource();
  6.                
  7.                 Producer pro = new Producer(r);
  8.                 Consumer con = new Consumer(r);
  9.                
  10.                 Thread t1 = new Thread(pro);
  11.                 Thread t2 = new Thread(pro);
  12.                 Thread t3 = new Thread(con);
  13.                 Thread t4 = new Thread(con);

  14.                 t1.start();
  15.                 t2.start();
  16.                 t3.start();
  17.                 t4.start();
  18.         }
  19. }

  20. class Resource
  21. {
  22.         private String name;
  23.         private int count = 1;
  24.         private boolean flag = false;
  25.         public synchronized void set(String name)
  26.         {
  27.                  while(flag)
  28.                         try
  29.                         {
  30.                                 wait();
  31.                         }
  32.                         catch (Exception e)
  33.                         {
  34.                         }
  35.                 this.name=name+"--"+count++;

  36.                 System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
  37.                 flag= true;
  38.                 this.notifyAll();
  39.         }
  40.         public synchronized void out()
  41.         {
  42.                 while(!flag)
  43.                         try
  44.                         {
  45.                                 wait();
  46.                         }
  47.                         catch (Exception e)
  48.                         {
  49.                         }
  50.                 System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
  51.                 flag=false;
  52.                 this.notifyAll();
  53.         }
  54. }
  55. class Producer implements Runnable
  56. {
  57.         private Resource res;
  58.         Producer(Resource res)
  59.         {
  60.                 this.res=res;
  61.         }
  62.         public void run()
  63.         {
  64.                 while (true)
  65.                 {
  66.                         res.set("+商品+");
  67.                 }
  68.         }
  69. }
  70. class Consumer implements Runnable
  71. {
  72.         private Resource res;
  73.         Consumer(Resource res)
  74.         {
  75.                 this.res=res;
  76.         }
  77.         public void run()
  78.         {
  79.                 while (true)
  80.                 {
  81.                         res.out();
  82.                 }
  83.         }
  84. }
复制代码
代码没有错,也能理解。但是我思考着思考着就钻到一个牛角尖出不来了,我在想一个问题,输出结果总是先打印生产者再打印消费者,这是为什么?为什么不会出现先打印消费者再打印生产者的问题?我觉得这是个很简单的问题,但是由于长时间奋斗现在这个时间我的脑子基本糊涂了,想不下去了,受不了了,求大神简单指导!

13 个回复

倒序浏览
个人觉得楼主真的该休息休息,你可以好好分析下你的代码,为什么会总是先打印出生产者,可以看下我下面红色的注解,再去想想。
class ProducerConsumerDemo
{
        public static void main(String[] args)
        {
                Resource r = new Resource();
               
                Producer pro = new Producer(r);
                Consumer con = new Consumer(r);
               
                Thread t1 = new Thread(pro);
                Thread t2 = new Thread(pro);
                Thread t3 = new Thread(con);
                Thread t4 = new Thread(con);

                t1.start();
                t2.start();
                t3.start();
                t4.start();
        }
}

class Resource
{
        private String name;
        private int count = 1;
        private boolean flag = false;//flag的初始值false,所以就算是消费者抢到了资源,他也没法去打印,而是处于等待状态
        public synchronized void set(String name)
        {
                 while(flag)//注意这个wait条件
                        try
                        {
                                wait();
                        }
                        catch (Exception e)
                        {
                        }
                this.name=name+"--"+count++;

                System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
                flag= true;
                this.notifyAll();
        }
        public synchronized void out()
        {
                while(!flag)//因为出事的flag是false,所以就算消费者抢到了资源,还是处于等待状态,也可以这么理解:库存没货,消费者就没东西消费,一定要等生产者生产出来商品以后,消费者才能消费
                        try
                        {
                                wait();
                        }
                        catch (Exception e)
                        {
                        }
                System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
                flag=false;
                this.notifyAll();
        }
}
class Producer implements Runnable
{
        private Resource res;
        Producer(Resource res)
        {
                this.res=res;
        }
        public void run()
        {
                while (true)
                {
                        res.set("+商品+");
                }
        }
}
class Consumer implements Runnable
{
        private Resource res;
        Consumer(Resource res)
        {
                this.res=res;
        }
        public void run()
        {
                while (true)
                {
                        res.out();
                }
        }
}
回复 使用道具 举报
本帖最后由 官文昌 于 2012-8-7 09:58 编辑

你想多了~~线程问题是抢资源,所以有一定的偶然性~~我把你的代码拿来运行后,我运行了三遍,就出现了先消费后生产的情况~~C:\Documents and Settings\Administrator\桌面

ANT`~]816U(4}95[XIYPDYD.jpg (38.43 KB, 下载次数: 30)

ANT`~]816U(4}95[XIYPDYD.jpg
回复 使用道具 举报
你想多了~~线程问题是抢资源,所以有一定的偶然性~~我把你的代码拿来运行后,我运行了三遍,就出现了先消费后生产的情况~~C:\Documents and Settings\Administrator\桌面
回复 使用道具 举报
本帖最后由 官文昌 于 2012-8-7 18:41 编辑

我把你的代码拿来运行后,我运行了三遍,就出现了先消费后生产的情况。
回复 使用道具 举报
  public synchronized void set(String name)

28.        {

29.                 while(flag)

30.                        try

31.                        {

32.                                wait();

33.                        }

34.                        catch (Exception e)

35.                        {

36.                        }

37.                this.name=name+"--"+count++;

38.

39.                System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);

40.                flag= true;

41.                this.notifyAll();

42.        }

43.        public synchronized void out()

44.        {

45.                while(!flag)

46.                        try

47.                        {

48.                                wait();

49.                        }

50.                        catch (Exception e)

51.                        {

52.                        }

53.                System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);

54.                flag=false;

55.                this.notifyAll();

56.        }

57.}

那就主要看这部分的代码了,刚一开始flag=flase; 要是先 进入同步方法set  循环不会得到执行,也就不会等待,所以会生产,要是先进入out   循环条件为真,  他就等待,知道他被叫醒。生产与消费只是这样反复执行的,一个先等待,另一个执行,只不过是你的代码通过一个标志的变量flag控制了程序,让set能够向下执行,二out要么没有获得执行,要么执行就等待。希望能帮到你,不懂在问。
回复 使用道具 举报
官文昌 发表于 2012-8-7 09:55
你想多了~~线程问题是抢资源,所以有一定的偶然性~~我把你的代码拿来运行后,我运行了三遍,就出现了先消费 ...

错了,想想也知道开始的数字是1,你那是循环太多次了,把最上面的给刷掉了,不要被编译器给骗了
回复 使用道具 举报
LZ适当休息休息  想想之前那几天讲的, 强行看视频 会崩溃的。
回复 使用道具 举报
按照道理,没有商品,消费者自然无法消费。这个程序也是这样体现的。Res类中flag初始值就是false.即便消费者线程最先抢到了CPU执行权,但一判断flag为假,便wait了.
回复 使用道具 举报
黑马王鹏 发表于 2012-8-7 10:02
错了,想想也知道开始的数字是1,你那是循环太多次了,把最上面的给刷掉了,不要被编译器给骗了 ...

受教了~~谢谢指教~~
回复 使用道具 举报
黑马王鹏 发表于 2012-8-7 10:02
错了,想想也知道开始的数字是1,你那是循环太多次了,把最上面的给刷掉了,不要被编译器给骗了 ...

受教了~~谢谢指教~~
回复 使用道具 举报
黑马王鹏 发表于 2012-8-7 09:43
个人觉得楼主真的该休息休息,你可以好好分析下你的代码,为什么会总是先打印出生产者,可以看下我下面红色 ...

额,原来在这里啊。谢谢了。
回复 使用道具 举报
刘向阳 发表于 2012-8-7 09:57
public synchronized void set(String name)

28.        {

明白了。谢谢。
回复 使用道具 举报
问题已解决。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马