小弟编写一个生产者消费者,碰到一个非常郁闷的问题,百思不得其解。请各位高手帮忙!
程序出现的问题是产品应该是先生产才能消费。但是确有先消费后生产的情况,
截图如下:代码如下:
package com.lcm;public class ProducterConsumer {
public static void main(String[] args) {
int stackSize = 15;
Stack stack = new Stack(stackSize); //存储量为15的容器
Producer p = new Producer(stack, 20);
Consumer c = new Consumer(stack, 20);
new Thread(p).start();
new Thread(c).start();
}
}class Thing {
int id;
public Thing(int id) {
this.id = id;
}
}class Stack {
int counter = 0;
int stackSize;
Thing[] things = null;
public Stack(int stackSize) {
this.stackSize = stackSize;
things = new Thing[stackSize];
}

public synchronized void push(Thing thing) { //生产
while(counter == stackSize) { //已经满了  等待消费
System.out.println("已经存满!等待消费。。");
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();
things[counter] = thing;
counter ++;
}

public synchronized Thing pop() { //消费
while(counter == 0) {
System.out.println("没有产品!等待生产。");
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();
counter --;
return things[counter];
}
}class Producer implements Runnable{
Stack stack;
int level;//生产水平

public Producer(Stack stack, int level) {
this.stack = stack;
this.level = level;
}

public void run() {
for(int i=0; i<level; i++) {
Thing thing = new Thing(i);
stack.push(thing);
System.out.println("生产: " + thing.id);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}class Consumer implements Runnable{
Stack stack;
int level;//生产水平

public Consumer(Stack stack, int level) {
this.stack = stack;
this.level = level;
}

public void run() {
for(int i=0; i<level; i++) {
Thing thing = stack.pop();
System.out.println("消费: " + thing.id);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

解决方案 »

  1.   

    程序没有问题。
    可能是打印结果的方法System.out.println()不同步,把打印结果的语句也放到同步方法中试试。
      

  2.   

    线程的执行顺序,按这种方式来启动的话,将不可预料。自然会出现错乱的情况。
    线程的执行顺序是由系统来决定的。thread.start()只是告诉系统该线程处于就绪状态,至于系统会不会选择它并让它运行就不一定了,毕竟还有那么多线程在跑。
      

  3.   

    不错在,run方法里面造成了不同步,应该放到加锁的那两个方法,因为只有他们才线程互斥,保证线程同步
      

  4.   

    帮楼主排个版,看着舒服点package com.lcm;
    public class ProducterConsumer
    {
       public static void main(String[] args)
       {
          int stackSize = 15;
          Stack stack = new Stack(stackSize);
          //存储量为15的容器 
    Producer p = new Producer(stack, 20);
          Consumer c = new Consumer(stack, 20);
          new Thread(p).start();
          new Thread(c).start();
       }
    }
    class Thing
    {
       int id;
       public Thing(int id)
       {
          this.id = id;
       }
    }
    class Stack
    {
       int counter = 0;
       int stackSize;
       Thing[] things = null;
       public Stack(int stackSize)
       {
          this.stackSize = stackSize;
          things = new Thing[stackSize];
       }
       public synchronized void push(Thing thing)
       {
          //生产 
    while(counter == stackSize)
          {
             //已经满了  等待消费 
    System.out.println("已经存满!等待消费。。");
             try
             {
                this.wait();
             }
             catch (InterruptedException e)
             {
                e.printStackTrace();
             }
          }
          this.notify();
          things[counter] = thing;
          counter ++;
       }
       public synchronized Thing pop()
       {
          //消费 
    while(counter == 0)
          {
             System.out.println("没有产品!等待生产。");
             try
             {
                this.wait();
             }
             catch (InterruptedException e)
             {
                e.printStackTrace();
             }
          }
          this.notify();
          counter --;
          return things[counter];
       }
    }
    class Producer implements Runnable
    {
       Stack stack;
       int level;
       //生产水平 public Producer(Stack stack, int level)
       {
          this.stack = stack;
          this.level = level;
       }
       public void run()
       {
          for(int i=0;
          i <level;
          i++)
          {
             Thing thing = new Thing(i);
             stack.push(thing);
             System.out.println("生产: " + thing.id);
             try
             {
                Thread.sleep(1000);
             }
             catch (InterruptedException e)
             {
                e.printStackTrace();
             }
          }
       }
    }
    class Consumer implements Runnable
    {
       Stack stack;
       int level;
       //生产水平 public Consumer(Stack stack, int level)
       {
          this.stack = stack;
          this.level = level;
       }
       public void run()
       {
          for(int i=0;
          i <level;
          i++)
          {
             Thing thing = stack.pop();
             System.out.println("消费: " + thing.id);
             try
             {
                Thread.sleep(500);
             }
             catch (InterruptedException e)
             {
                e.printStackTrace();
             }
          }
       }
    }