Java线程-并发协作-生产者消费者模型

不管任何语言,生产消费者模型都是最经典的,就像每一门编程语言“Hello World!”一样。
准确来说,应该是“生产-消费-仓储”模型,离开了仓储,生产者消费者模型就显得没有说服力了。
业务描述如下:
(1)、生产者在仓库未满时进行生产,仓库满了,则停止生产。
(2)、消费者仅仅在仓库有产品时才能进行消费,空仓则进行等待。
(3)、当消费者发现仓库没有产品可以消费时,就通知生产者进行生产。
(4)、生产者在生产出产品以后,应该通知等待的消费者进行消费。
代码如下:

package Test;

public class Main {

    public static void main(String args[]){
        GoDown goDown=new GoDown(30);

        Consumer consumer1=new Consumer(50,goDown);
        Consumer consumer2=new Consumer(20,goDown);
        Consumer consumer3=new Consumer(30,goDown);

        Producer producer1=new Producer(10,goDown);
        Producer producer2=new Producer(10,goDown);
        Producer producer3=new Producer(10,goDown);
        Producer producer4=new Producer(10,goDown);
        Producer producer5=new Producer(10,goDown);
        Producer producer6=new Producer(10,goDown);
        Producer producer7=new Producer(80,goDown);

        consumer1.start();
        consumer2.start();
        consumer3.start();
        producer1.start();
        producer2.start();
        producer3.start();
        producer4.start();
        producer5.start();
        producer6.start();
        producer7.start();
    }
}

/**
 * 仓库
 */
class GoDown {
    public static final int max_size=100;//库存量
    public int curNum;//当前库存量

    GoDown(){
    }
    GoDown(int curNum){
        this.curNum=curNum;
    }

    /**
     * 生产指定数量的产品
     * @param needNum
     */
    public synchronized void produce(int needNum){
        //测试是否需要生产
        while ((this.curNum+needNum)>max_size){
            System.out.println("要生产的产品数量:"+needNum+",超过剩余库存量:"+(max_size-this.curNum)+",暂时不能执行生产任务");
            try {
                //当前的生产者等待
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //满足条件则进行生产,并更改当前库存量
        this.curNum+=needNum;
        System.out.println("已经生产了"+needNum+"个产品,现库存量为:"+this.curNum);
        //唤醒在此监视器上等待的所有的线程
        notifyAll();
    }

    /**
     * 消费指定数量的产品
     * @param needNum
     */
    public synchronized void consume(int needNum){
        //测试是否可以消费
        while (this.curNum<needNum){
            try {
                //当前的生产线程等待
                wait();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        //满足条件则进行消费
        this.curNum-=needNum;
        System.out.println("已经消费了"+needNum+"个产品,现库存量为:"+this.curNum);
        //唤醒在此对象监视器上等待的所有的线程
        notifyAll();
    }
}

/**
 * 生产者
 */
class Producer extends Thread {
    private int needNum;//生产产品的数量
    private GoDown goDown;//库存
    Producer(int needNum,GoDown goDown){
        this.needNum=needNum;
        this.goDown=goDown;
    }

    /**
     * 生产指定数量的产品
     */
    @Override
    public void run() {
        goDown.produce(this.needNum);
    }
}

/**
 * 消费者
 */
class Consumer extends Thread {
    private int needNum;//消费产品的数量
    private GoDown goDown;//库存
    Consumer(int needNum,GoDown goDown){
        this.needNum=needNum;
        this.goDown=goDown;
    }

    /**
     * 消费指定数量的产品
     */
    @Override
    public void run() {
        goDown.consume(this.needNum);
    }
}

运行结果如下:

已经消费了20个产品,现库存量为:10
已经生产了10个产品,现库存量为:20
已经生产了10个产品,现库存量为:30
已经生产了10个产品,现库存量为:40
已经消费了30个产品,现库存量为:10
已经生产了10个产品,现库存量为:20
已经生产了10个产品,现库存量为:30
已经生产了10个产品,现库存量为:40
要生产的产品数量:80,超过剩余库存量:60,暂时不能执行生产任务

说明:
当不能满足生产者和消费者的条件的时候,调用对象的wait方法,wait方法时释放当前线程所获得的锁,并调用对象的notifyAll()方法,通知该对象上的其它线程,使得其它线程继续执行,使得整个生产者和消费者得以运行。
notifyAll方法起到的是一个通知作用,不释放锁,也不获取锁,只告诉该对象等待的线程“可以竞争执行了”。

猜你喜欢

转载自blog.csdn.net/qq_24630433/article/details/88240494