Java多线程之生产者-消费者模式

问题描述

假如汽车公司只有一个生产车间, 一间存储仓库(仓库可存储做多n辆车),该公司只生产一种车型。现在需要模仿生产、销售过程。每生产一辆汽车,需要送入仓库临时存储,当仓库满后,停止生产,车辆的销售有一个前提条件是,库存大于零。

问题分析

使用面向对象的思维,我们需要考虑类的设计
生产车间(生产者):生产者生产汽车放入仓库,这个类包括生产汽车和调入指定库存两个方法
消费者:汽车取出仓库,这个类具有取出汽车的方法
仓库:库存数量,这个类需要统计汽车数量,当库存已满或者库存为空是发出消息
数据结构设计
仓库被设计成栈结构
考虑到汽车生产和销售是两个独立的过程,有必要使用多线程

代码描述

public class ProducersConsumers {
    public static void main(String[] args) {
        Storage storage = new Storage();
        Producer producer = new Producer(storage);
        Consumer consumer = new Consumer(storage);
        new Thread(producer).start();
        new Thread(consumer).start();
    }

}
class Car{
    int id;   //每辆汽车取一个id
    public Car(int id) {
        this.id = id;
    }
}
class Storage{
    int index;   //用数组实现栈结构
    private static final int MAX_NUM = 20;
    Car[] carStack = new Car[MAX_NUM];

    //入库
    public  synchronized void push(Car car){
        while (index == MAX_NUM){
            try {
                this.wait(); //仓库满时,入库线程等待
            }catch (InterruptedException e){}
        }
        this.notify(); //有可能空唤醒
        carStack[index] = car;
        index++;
    }
    //出库
    public synchronized Car pop( ){
        while (index == 0){
            try {
                this.wait(); //库存为空时,出库线程等待
            }catch (InterruptedException e){}
        }
        this.notify();
        index--;
        return carStack[index];
    }
}
class Producer implements Runnable{
    Storage storage = null;
    //每一辆汽车都会放入仓库,本例只有一个仓库
    public Producer(Storage storage) {
        this.storage = storage;
    }

    public void run( ) {
        for (int i = 0; i < 20; i++) {
            Car car = new Car(i);
            storage.push(car);
            System.out.println("生产了"+i+"辆汽车");
            try {
                Thread.sleep(100);
            }catch (InterruptedException e){}
        }

    }
}
class Consumer implements Runnable{
    Storage storage = null;
    //从仓库取出一辆汽车
    public Consumer(Storage storage) {this.storage = storage;}
    public void run( ) {
        for (int i = 0; i < 20; i++) {
            storage.pop();
            System.out.println("卖出了"+i+"辆汽车");
            try {
                Thread.sleep(100);
            }catch (InterruptedException e){}
        }
    }
}
上面的问题中,如果存在多个生产者和多个消费者,上面的问题将变得复杂。在这个问题中,最重要的地方在于有多个进程可以访问公共资源,因此首先要考虑进程的同步问题,不能让两个线程交叉执行(在这个例子中可以理解为,汽车入库和出库必须经过一扇很狭小的门,当然实际中并不是这样)。第二个需要考虑的问题是线程之间的通信问题,表现为 线程的等待和唤醒机制。当然,在实际应用中,任何产生数据的程序都可以称为生产者,而删除数据的一方可被视为消费者。
另外,在实际编码中,恰当使用锁的粒度、使用线程池、使用缓冲队列等都是可以提高的地方。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值