/*5个生产者,1个篮子,3个消费者;
其中每个生产者一次能生产20个产品,并将产品放入篮子;
篮子总共能放5个产品;
消费者每次从篮子顶端取出产品消费;*/
public class ProducterConsumer 
{
    public static void main(String[] args)
   {
        SyncStack ss = new SyncStack();
        Producer p1 = new Producer(ss);
        Producer p2 = new Producer(ss);
        Producer p3 = new Producer(ss);
        Producer p4 = new Producer(ss);
        Producer p5 = new Producer(ss);
        Consumer c1 = new Consumer(ss);
        Consumer c2 = new Consumer(ss);
        Consumer c3 = new Consumer(ss);
        new Thread(p1).start();
        new Thread(p2).start();
        new Thread(p3).start();
        new Thread(p4).start();
        new Thread(p5).start();
        new Thread(c1).start();
        new Thread(c2).start();
        new Thread(c3).start();
    }
}class ChanPin
{
     public static int counter = 0;
     private int id;
 
     public ChanPin()
    {
         this.id = counter++;
    }
 
    public String toString()
    {
        return "产品" + id;
    }
}
//篮子
class SyncStack
{
     int index = 0;
     ChanPin[] arrCP = new ChanPin[5];
 
     public synchronized  ChanPin push(ChanPin cp)
    {
         while(index == arrCP.length)
        {
          System.out.println("篮子满了");
            try
           {
             //pop();
               this.wait();
           } 
           catch (Exception e)
           {
               e.printStackTrace();
           }
    }
    this.notifyAll();//让所有的线程从wait中恢复过来,继续执行后面的语句
    System.out.println("??????"+cp);
    arrCP[index] = cp;
    index++;  
    System.out.println("生产一个产品,篮子里有+++++>" + index + "个");
    return cp;
}
 
public synchronized ChanPin pop()
{
    while(index == 0)
    {
     System.out.println("篮子空了");
       try
       {
        System.out.println("index      "+index);
           this.wait();
       } 
       catch (Exception e)
       {
            e.printStackTrace();
       }
   }
   this.notifyAll();
   index--; 
   System.out.println("消费一个产品,篮子里有----->" + index + "个");
  return arrCP[index];
   }
}
//生产者
class Producer implements Runnable
{
   SyncStack ss = null;
 
   Producer(SyncStack ss)
   {
       this.ss = ss;
   }
 
   public void run()
   {
        for(int i=0; i<20; i++)
       {
         ChanPin cp = new ChanPin();   
           ss.push(cp);    
           try
           {
               Thread.sleep((int)(Math.random()*10));
           }
           catch(InterruptedException e)
           {
                 e.printStackTrace();
           }
       }
    }
}
//消费者
class Consumer implements Runnable
{
     SyncStack ss = null;
 
     Consumer(SyncStack ss)
    {
        this.ss = ss;
    }
 
    public void run()
    {
         for(int i=0; i<20; i++)
         {
             ss.pop();
             try
             {
                 Thread.sleep((int)(Math.random()*10));
             }
             catch(InterruptedException e)
             {
                  e.printStackTrace();
             }
         }
    }
}执行结果如下:
??????产品0
生产一个产品,篮子里有+++++>1个
??????产品1
生产一个产品,篮子里有+++++>2个
??????产品2
生产一个产品,篮子里有+++++>3个
??????产品3
生产一个产品,篮子里有+++++>4个
??????产品4
生产一个产品,篮子里有+++++>5个
消费一个产品,篮子里有----->4个
消费一个产品,篮子里有----->3个
消费一个产品,篮子里有----->2个
??????产品5
生产一个产品,篮子里有+++++>3个
??????产品6
生产一个产品,篮子里有+++++>4个
??????产品7
生产一个产品,篮子里有+++++>5个
消费一个产品,篮子里有----->4个
消费一个产品,篮子里有----->3个
消费一个产品,篮子里有----->2个
??????产品9
生产一个产品,篮子里有+++++>3个
??????产品8
生产一个产品,篮子里有+++++>4个
??????产品10
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品12
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品14
生产一个产品,篮子里有+++++>5个
消费一个产品,篮子里有----->4个
消费一个产品,篮子里有----->3个
??????产品13
生产一个产品,篮子里有+++++>4个
??????产品11
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品17
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
消费一个产品,篮子里有----->3个
??????产品19
生产一个产品,篮子里有+++++>4个
??????产品18
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品21
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
消费一个产品,篮子里有----->3个
??????产品22
生产一个产品,篮子里有+++++>4个
??????产品15
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品20
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品24
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品16
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品25
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品28
生产一个产品,篮子里有+++++>5个
消费一个产品,篮子里有----->4个
??????产品27
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品31
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品26
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品33
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品23
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品32
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品29
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品35
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品37
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品38
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品39
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品34
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品30
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品40
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品44
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品36
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品45
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品41
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品46
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品48
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品49
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品50
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品52
生产一个产品,篮子里有+++++>5个
消费一个产品,篮子里有----->4个
??????产品51
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品54
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品43
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品55
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品42
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品56
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品47
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品59
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品53
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品61
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
消费一个产品,篮子里有----->3个
??????产品57
生产一个产品,篮子里有+++++>4个
??????产品58
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品63
生产一个产品,篮子里有+++++>5个
消费一个产品,篮子里有----->4个
??????产品62
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品67
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
篮子满了
消费一个产品,篮子里有----->4个
??????产品68
生产一个产品,篮子里有+++++>5个
篮子满了
篮子满了
篮子满了
篮子满了
篮子满了疑问:为什么不出现篮子空了的情况呢??线程停止的条件是什么??初学者,见笑了,谢谢指教……

解决方案 »

  1.   

    在篮子满了时候就是this.wait();方法后加一个this.notify()触发一个下一个线程执行。
    在空了的时候也加上。消费都也加上。
    线程停止的条件是stop()就行了。
      

  2.   

    http://zhangjunhd.blog.51cto.com/113473/71387
      

  3.   

    我有加notify(),但还是不行哦……
      

  4.   

    notify的位置不对。
    应该加在做完事情之后。
    push函数加在这个地方:
    index++;  
    this.notifyAll();pop函数里应该加在这个地方
    index--; 
    this.notifyAll();但是你的程序不会结束的原因不在于此,而在于生产了100个产品,而只消费了60个,
    因此剩下的40个产品里面有35个永远在排队,等待加入 ChanPin[] arrCP数组中,所以程序永远也不会结束。
      

  5.   

    this.notifyAll()的位置改了,但还是不会出现篮子空的情况……
      

  6.   

    我知道什么原因了。
    是因为你的生产者太多了。
    当还没有消费完就有生产了。所以只能满了。
    你可以去掉两个生产都。空了就出来了。
    记住。this.notify() ;
    public class SyncStack { int index = 0;
    ChanPin[] arrCP = new ChanPin[5]; public synchronized ChanPin push(ChanPin cp) {
    while (index == arrCP.length) {
    System.out.println("篮子满了");
    try {
    // pop();
    this.wait();

    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    this.notifyAll();// 让所有的线程从wait中恢复过来,继续执行后面的语句
    System.out.println("??????" + cp);
    arrCP[index] = cp;
    index++;
    this.notify() ;
    System.out.println("生产一个产品,篮子里有+++++>" + index + "个");
    return cp;
    } public synchronized ChanPin pop() {
    while (index == 0) {
    System.out.println("篮子空了");
    try {
    System.out.println("index      " + index);
    this.wait();

    } catch (Exception e) {
    e.printStackTrace();
    }
    }

    index--;
    this.notify() ;
    System.out.println("消费一个产品,篮子里有----->" + index + "个");
    return arrCP[index];
    }}
      

  7.   

    不要用this.notifyAll();用this.notify();
      

  8.   

    问题1:处理机每次的调度是不同的,为线程分配的时间片也不一样。
    多运行几次。会出现空篮子的情况。问题2:生产者线程多于消费者线程,而且循环次数都是20次,所以不会停止。
    改进方法一:
    让生产者线程也是3个,这样就能正常停止。
    改进方法二:
    把消费者线程的循环次数改大一些比方说循环40次,但这还不够,这样还不会停止,
    因为篮子空的情况而被阻塞。
    把消费者线程改为守护线程就行了:                Thread t1 = new Thread(c1);
    Thread t2 = new Thread(c1);
    Thread t3 = new Thread(c1);
    t1.setDaemon(true);
    t2.setDaemon(true);
    t3.setDaemon(true);
    t1.start();
    t2.start();
    t3.start();守护线程是为用户线程服务,垃圾回收机制就是一守护线程。
    当生产者这个用户线程停止时,消费者这个守护线程也自动终止。