需求:

1 同一时间内只能有一个生产者生产    

2 同一时间内只能有一个消费者消费    

3 生产者生产的同时消费者不能消费    

4 消费者消费的同时生产者不能生产 

 消费者和生产者只能有一个在工作。

 ----同步方法或者同步代码快

5 共享空间空时消费者不能继续消费    

6 共享空间满时生产者不能继续生产    

注意:

1、Wait、notify、notifyAll方法的调用必须放在同步方法和同步代码块里面


是调用“同步锁”对象的Wait、notify、notifyAll方法而不是线程对象的方法。


//定义一个仓库类
public class Storage {
     /** 

      * Max_num表示仓库的最大容量 

      * cur_num表示当前仓库的库存 

      */ 

     static int Max_num = 100; 

      

     private int cur_num = 50; 

      

     //入库的方法 

    public synchronized void in(int num){
//如果当前库存加上生产者准备存放的量大于仓库的最大容量,则将该线程挂起,释放当前进程锁
         while(this.cur_num + num > Max_num){ 

             try { 

                 System.out.println(Thread.currentThread().getName() + "入库失败,仓库已溢出!请及时消费"); 

                 this.wait(); 

             } catch (InterruptedException e) { 

                 e.printStackTrace(); 

             } 

         } 

         this.notify(); 

         cur_num += num; 

         System.out.println(Thread.currentThread().getName() + "入库" + num +",库存为:" + cur_num); 

     } 

      

     //出库的方法 

    public synchronized void out(int num){
//如果当前消费者的需求量大于仓库的库存,则将该线程挂起,释放当前进程锁
         while(num > cur_num){ 

             try { 

                 System.out.println( Thread.currentThread().getName() + "出库失败,库存不足!请及时补货"); 

                 this.wait(); 

             } catch (InterruptedException e) { 

                 e.printStackTrace(); 

             } 

         } 

         this.notify(); 

         cur_num -= num; 

         System.out.println(Thread.currentThread().getName() + "出库" + num +",库存为:" + cur_num); 

    }
//接着定义消费者线程类
public class Customer extends Thread{
     Storage s; //根据仓库的对象实现线程同步
     private int num; //当前消费者的需求量
     
     /**
      * @param name 输出当前线程名(也就是消费者名)
      * @param s    传入仓库对象
      * @param num 消费者的需求量
      */
     public Customer(String name,Storage s,int num){
         super(name);//线程名
         this.s = s;
         this.num = num;
     }
     
     public void run(){
         try {
             Thread.sleep(500);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         //调用仓库中的出库方法,将需求变量传入
         s.out(num);
     }
 }//还需定义一个生产者线程类
public class Producer extends Thread{
     Storage s; //根据仓库的对象实现线程同步
     private int num;//当生产者的生产量
     /**
      * @param name 输出当前线程名(也就是生产者名)
      * @param s    传入仓库对象
      * @param num 生产者的生产量
      */
     public Producer(String name,Storage s,int num){
         super(name); //线程名
         this.s = s;
         this.num = num;
     }
     
     public void run(){
         try {
             Thread.sleep(500);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         //调用仓库中的入库方法,将准备入库的数量传入
         s.in(num);
     }
 }//最后,创建Test类进行测试
public class Test {

     public static void main(String[] args) {
         //创建一个共同的仓库对象(注:这里因为是消费者线程和生产者线程要实现同步,所以只能new一个仓库对象)
         Storage s = new Storage();
         
         //创建生产者线程:
         /**
          * 传入线程名、对象、出入库的数量
          */
         Producer p1 = new Producer("P_1", s, 50);
         Producer p2 = new Producer("P_2", s, 20);
         Producer p3 = new Producer("P_3", s, 30);
         
         //创建消费者进程:
         Customer c1 = new Customer("C_1", s, 60);
         Customer c2 = new Customer("C_2", s, 30);
         Customer c3 = new Customer("C_3", s, 60);
         //启动线程
         p1.start();p2.start();p3.start();
         c1.start();c2.start();c3.start();       
     }
 }