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

问题描述

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

问题分析

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

代码描述

  1. public class ProducersConsumers {  
  2.     public static void main(String[] args) {  
  3.         Storage storage = new Storage();  
  4.         Producer producer = new Producer(storage);  
  5.         Consumer consumer = new Consumer(storage);  
  6.         new Thread(producer).start();  
  7.         new Thread(consumer).start();  
  8.     }  
  9.   
  10. }  
  11. class Car{  
  12.     int id;   //每辆汽车取一个id  
  13.     public Car(int id) {  
  14.         this.id = id;  
  15.     }  
  16. }  
  17. class Storage{  
  18.     int index;   //用数组实现栈结构  
  19.     private static final int MAX_NUM = 20;  
  20.     Car[] carStack = new Car[MAX_NUM];  
  21.   
  22.     //入库  
  23.     public  synchronized void push(Car car){  
  24.         while (index == MAX_NUM){  
  25.             try {  
  26.                 this.wait(); //仓库满时,入库线程等待  
  27.             }catch (InterruptedException e){}  
  28.         }  
  29.         this.notify(); //有可能空唤醒  
  30.         carStack[index] = car;  
  31.         index++;  
  32.     }  
  33.     //出库  
  34.     public synchronized Car pop( ){  
  35.         while (index == 0){  
  36.             try {  
  37.                 this.wait(); //库存为空时,出库线程等待  
  38.             }catch (InterruptedException e){}  
  39.         }  
  40.         this.notify();  
  41.         index--;  
  42.         return carStack[index];  
  43.     }  
  44. }  
  45. class Producer implements Runnable{  
  46.     Storage storage = null;  
  47.     //每一辆汽车都会放入仓库,本例只有一个仓库  
  48.     public Producer(Storage storage) {  
  49.         this.storage = storage;  
  50.     }  
  51.   
  52.     public void run( ) {  
  53.         for (int i = 0; i < 20; i++) {  
  54.             Car car = new Car(i);  
  55.             storage.push(car);  
  56.             System.out.println("生产了"+i+"辆汽车");  
  57.             try {  
  58.                 Thread.sleep(100);  
  59.             }catch (InterruptedException e){}  
  60.         }  
  61.   
  62.     }  
  63. }  
  64. class Consumer implements Runnable{  
  65.     Storage storage = null;  
  66.     //从仓库取出一辆汽车  
  67.     public Consumer(Storage storage) {this.storage = storage;}  
  68.     public void run( ) {  
  69.         for (int i = 0; i < 20; i++) {  
  70.             storage.pop();  
  71.             System.out.println("卖出了"+i+"辆汽车");  
  72.             try {  
  73.                 Thread.sleep(100);  
  74.             }catch (InterruptedException e){}  
  75.         }  
  76.     }  
  77. }  
上面的问题中,如果存在多个生产者和多个消费者,上面的问题将变得复杂。在这个问题中,最重要的地方在于有多个进程可以访问公共资源,因此首先要考虑进程的同步问题,不能让两个线程交叉执行(在这个例子中可以理解为,汽车入库和出库必须经过一扇很狭小的门,当然实际中并不是这样)。第二个需要考虑的问题是线程之间的通信问题,表现为 线程的等待和唤醒机制。当然,在实际应用中,任何产生数据的程序都可以称为生产者,而删除数据的一方可被视为消费者。
另外,在实际编码中,恰当使用锁的粒度、使用线程池、使用缓冲队列等都是可以提高的地方。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值