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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

//定义产品类
class Goods{
        private String name;
        boolean flag=false;//flag用于判断产品是否还有。
        int count= 0;
        //定义函数,提供创建产品信息,包括产品名称和序号。序号是自动增加的。
        public void setGoods(String name){
                this.name=name;
                ++count;
        }
        //定义函数生产产品
        public synchronized void inputGoods(){
                while(flag){
                        try{this.wait();}catch(Exception e){}//若有产品,就让当前线程等待。
                }
                setGoods("王哈哈");
                System.out.println(Thread.currentThread().getName()+"生产了............."+this.name+this.count+"产品");
                flag=true;//将产品状态修改为有产品。
                this.notifyAll();//唤醒其他线程
        }
        //定义函数消费产品
        public synchronized void OutputGoods(){
                while(!flag){
                        try{this.wait();}catch(Exception e){}//若无产品,就让当前线程等待。
                }
                System.out.println(Thread.currentThread().getName()+"消费了"+this.name+this.count);
                flag=false;//将产品状态修改为无产品。
                this.notifyAll();//唤醒其他线程
        }
}
//定义生产者线程
class Producter implements Runnable{
        private Goods goods;
        public Producter(Goods goods){
                this.goods=goods;
        }
        public void run(){
                while(true){
                        goods.inputGoods();
                }
        }
}
//定义消费者线程
class Consumer implements Runnable{
        private Goods goods;
        public Consumer(Goods goods){
                this.goods=goods;
        }
        public void run(){
                while(true){
                        goods.OutputGoods();
                }
        }
}
public class Shishi {
        public static void main(String[] args) {
                Goods goods=new Goods();
                //启动两个生产线程
                new Thread(new Producter(goods)).start();
                new Thread(new Producter(goods)).start();
                //启动两个消费线程。
                new Thread(new Consumer(goods)).start();
                new Thread(new Consumer(goods)).start();
        }
}

打印输出结果为:
Thread-1生产了.............王哈哈52821产品
Thread-2消费了王哈哈52821
Thread-0生产了.............王哈哈52822产品
Thread-3消费了王哈哈52822
Thread-1生产了.............王哈哈52823产品
Thread-2消费了王哈哈52823
等等等

我定义的产品序号count是从0开始的,为什么不从0开始打印,而直接越到了52821,求大神解决!

4 个回复

正序浏览
席杰 发表于 2014-8-10 15:53
我想起来了,毕老师好像说过,打印输出运行时本身也是一个独立的线程,当程序运行时,打印输出线程没有我 ...

不是。你别想多了,你的程序一点问题没有。就是运行速度太快,之前的结果翻了N屏再也看不见了而已。你拿下面这段代码试试就明白了。除了加入sleep,其他的一点没改:
  1. class Goods{
  2.     private String name;
  3.     boolean flag=false;//flag用于判断产品是否还有。
  4.     int count= 0;
  5.     //定义函数,提供创建产品信息,包括产品名称和序号。序号是自动增加的。
  6.     public void setGoods(String name){
  7.             this.name=name;
  8.             ++count;
  9.     }
  10.     //定义函数生产产品
  11.     public synchronized void inputGoods(){
  12.             while(flag){
  13.                     try{this.wait();}catch(Exception e){}//若有产品,就让当前线程等待。
  14.             }
  15.             setGoods("王哈哈");
  16.             System.out.println(Thread.currentThread().getName()+"生产了............."+this.name+this.count+"产品");
  17.             try {
  18.             Thread.sleep(1000);
  19.             } catch(InterruptedException e) {}
  20.             flag=true;//将产品状态修改为有产品。
  21.             this.notifyAll();//唤醒其他线程
  22.     }
  23.     //定义函数消费产品
  24.     public synchronized void OutputGoods(){
  25.             while(!flag){
  26.                     try{this.wait();}catch(Exception e){}//若无产品,就让当前线程等待。
  27.             }
  28.             System.out.println(Thread.currentThread().getName()+"消费了"+this.name+this.count);
  29.             try {
  30.             Thread.sleep(1000);
  31.             } catch(InterruptedException e) {}
  32.             flag=false;//将产品状态修改为无产品。
  33.             this.notifyAll();//唤醒其他线程
  34.     }
  35. }
  36. //定义生产者线程
  37. class Producter implements Runnable{
  38.     private Goods goods;
  39.     public Producter(Goods goods){
  40.             this.goods=goods;
  41.     }
  42.     public void run(){
  43.             while(true){
  44.                     goods.inputGoods();
  45.             }
  46.     }
  47. }
  48. //定义消费者线程
  49. class Consumer implements Runnable{
  50.     private Goods goods;
  51.     public Consumer(Goods goods){
  52.             this.goods=goods;
  53.     }
  54.     public void run(){
  55.             while(true){
  56.                     goods.OutputGoods();
  57.             }
  58.     }
  59. }
  60. public class Tests {
  61.     public static void main(String[] args) {
  62.             Goods goods=new Goods();
  63.             //启动两个生产线程
  64.             new Thread(new Producter(goods)).start();
  65.             new Thread(new Producter(goods)).start();
  66.             //启动两个消费线程。
  67.             new Thread(new Consumer(goods)).start();
  68.             new Thread(new Consumer(goods)).start();
  69.     }
  70. }
复制代码
回复 使用道具 举报
fantacyleo 发表于 2014-8-10 15:38
程序没问题,只不过运行速度太快,前面的都一闪而过罢了,你在input和output方法中加一些Thread.sleep()就 ...

我想起来了,毕老师好像说过,打印输出运行时本身也是一个独立的线程,当程序运行时,打印输出线程没有我自定义的线程运行快,而导致我自定义的线程以运行好长时间,count值以很大,但是打印线程还没工作,从而导致打印延时。我这样说对不对?
回复 使用道具 举报
程序没问题,只不过运行速度太快,前面的都一闪而过罢了,你在input和output方法中加一些Thread.sleep()就好了
回复 使用道具 举报
我记得我上次的做法是,生存者 他的库存最多1000。然后消费者从库存里面拿(!=0)  就随便拿。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马