Welcome 微信登录

首页 / 软件开发 / JAVA / Java多线程:“基础篇”11之生产消费者问题

Java多线程:“基础篇”11之生产消费者问题2014-06-02 cnblogs skywang123451. 生产/消费者模型

生产/消费者问题是个非常典型的多线程问题,涉及到的对象包括“生产者”、“消 费者”、“仓库”和“产品”。他们之间的关系如下:

(01) 生产者仅仅在仓储未满时候生产,仓满则停止生产。

(02) 消费者仅仅在仓储有产品时候才能消费,仓空则等待。

(03) 当消费者发现仓储没产品可消费时候会通知生产者生产。

(04) 生产者在生产出可消费产品时候,应该通知等待的消费者去消费。

2. 生产/消费者实现

下面通过wait()/notify()方式实现该模型(后面在学习了线程池相关内容之后,再通过其它方式实现 生产/消费者模型)。源码如下:

// Demo1.java// 仓库class Depot {private int capacity;// 仓库的容量private int size;// 仓库的实际数量public Depot(int capacity) {this.capacity = capacity;this.size = 0;}public synchronized void produce(int val) {try { // left 表示“想要生产的数量”(有可能生产量太多,需多此生产)int left = val;while (left > 0) {// 库存已满时,等待“消费者”消费产品。while (size >= capacity)wait();// 获取“实际生产的数量”(即库存中新增的数量)// 如果“库存”+“想要生产的数量”>“总的容量”,则“实际增量”=“总的容量”-“当前容量”。(此时填满仓库)// 否则“实际增量”=“想要生产的数量”int inc = (size+left)>capacity ? (capacity-size) : left;size += inc;left -= inc;System.out.printf("%s produce(%3d) --> left=%3d, inc=%3d, size=%3d
", Thread.currentThread().getName(), val, left, inc, size);// 通知“消费者”可以消费了。notifyAll();}} catch (InterruptedException e) {}} public synchronized void consume(int val) {try {// left 表示“客户要消费数量”(有可能消费量太大,库存不够,需多此消费)int left = val;while (left > 0) {// 库存为0时,等待“生产者”生产产品。while (size <= 0)wait();// 获取“实际消费的数量”(即库存中实际减少的数量)// 如果“库存”<“客户要消费的数量”,则“实际消费量”=“库存”;// 否则,“实际消费量”=“客户要消费的数量”。int dec = (size<left) ? size : left;size -= dec;left -= dec;System.out.printf("%s consume(%3d) <-- left=%3d, dec=%3d, size=%3d
", Thread.currentThread().getName(), val, left, dec, size);notifyAll();}} catch (InterruptedException e) {}}public String toString() {return "capacity:"+capacity+", actual size:"+size;}} // 生产者class Producer {private Depot depot;public Producer(Depot depot) {this.depot = depot;}// 消费产品:新建一个线程向仓库中生产产品。public void produce(final int val) {new Thread() {public void run() {depot.produce(val);}}.start();}}// 消费者class Customer {private Depot depot;public Customer(Depot depot) {this.depot = depot;}// 消费产品:新建一个线程从仓库中消费产品。public void consume(final int val) {new Thread() {public void run() {depot.consume(val);}}.start();}}public class Demo1 {public static void main(String[] args) {Depot mDepot = new Depot(100);Producer mPro = new Producer(mDepot);Customer mCus = new Customer(mDepot);mPro.produce(60);mPro.produce(120);mCus.consume(90);mCus.consume(150);mPro.produce(110);}}