java多线程同步案例之--生产者消费者模型

需求:

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

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

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

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

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

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

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

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

注意:

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

是调用“同步锁”对象的WaitnotifynotifyAll方法而不是线程对象的方法。

//定义一个仓库类

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();      
    }
}


你可能感兴趣的:(java多线程同步案例)