生產者和消費者是我們會經常遇到的問題,今天抽時間編寫了這種情境的實現。所謂生產者就是產生某種資料的一個對象(通常是一個線程),生產者生產的資料放到一個倉庫中,消費者直接從倉庫中提取資料即可。所謂消費者就是從倉庫中提取資料的對象,通常是另外一個線程。下面生產者生產麵包,放到倉庫中,供消費者使用的例子。
1. 對象說明:
Bread:生產者負責生產的麵包
BreadCache:生產者生產的麵包存放的倉庫,也就是一個緩衝地址
Producer:負責生產麵包的線程,生產出的麵包放到BreadCache倉庫中
Consumer:負責消費麵包的線程,負責從BreadCache倉庫中取麵包進行消費
2. 範例程式碼
package com.csdn.algorithm.producer.consumer;/** * 生產者和消費者樣本。<BR> * Bread:生產者負責生產的麵包<BR> * BreadCache:生產者生產的麵包存放的倉庫,也就是一個緩衝地址<br> *Producer:負責生產麵包的線程,生產出的麵包放到BreadCache倉庫中<BR> *Consumer:負責消費麵包的線程,負責從BreadCache倉庫中取麵包進行消費<BR> * * @author Administrator * */public class ProducerConsumer {/** * 主方法 * * @param args */public static void main(String[] args) {//調用內部類,也可以單獨作為一個類檔案ProducerConsumer aInstance = new ProducerConsumer();BreadCache currBreadCache = aInstance.new BreadCache();Producer p = aInstance.new Producer(currBreadCache);Consumer c = aInstance.new Consumer(currBreadCache);// 線程new Thread(p).start();new Thread(c).start();}// 定義一個麵包類,麵包只有IDclass Bread {int m_nId;public Bread(int _id) {super();this.m_nId = _id;}public String toString() {return this.m_nId + "";}}// 定義存放生產者生產出的麵包,也就是麵包的緩衝class BreadCache {private int m_nIndex = 0;Bread[] m_oBreadCache = new Bread[10];public BreadCache() {super();}/** *向倉庫中放入一個麵包,如果倉庫已經滿了,則等待 * * @param _newBread */public synchronized void push(Bread _newBread) {while (m_nIndex == m_oBreadCache.length) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}// 放麵包m_oBreadCache[m_nIndex] = _newBread;m_nIndex++;// 通知所有等待取麵包的線程this.notifyAll();}/** * 從倉庫中取一個麵包,如果沒有麵包,則等待 * * @return */public synchronized Bread pop() {while (m_nIndex == 0) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}m_nIndex--;this.notifyAll();return m_oBreadCache[m_nIndex];}}// 生產者線程,一個線程只生產20個麵包class Producer implements Runnable {BreadCache m_oCache = null;public Producer(BreadCache _cache) {m_oCache = _cache;}@Overridepublic void run() {for (int i = 0; i < 20; i++) {Bread aBread = new Bread(i);m_oCache.push(aBread);System.out.println("生產[ " + aBread + " ]");try {Thread.currentThread().sleep((int) (Math.random() * 200));} catch (InterruptedException e) {e.printStackTrace();}}}}// 消費線程,一個線程消費掉20個麵包class Consumer implements Runnable {BreadCache m_oCache = null;public Consumer(BreadCache _cache) {m_oCache = _cache;}@Overridepublic void run() {for (int i = 0; i < 20; i++) {Bread aBread = m_oCache.pop();System.out.println("消費[ " + aBread + " ]");try {Thread.currentThread().sleep((int) (Math.random() * 200));} catch (InterruptedException e) {e.printStackTrace();}}}}}