生產者/消費者模式

在實際的軟件開發過程當中,常常會碰到以下場景:某個模塊負責產生數據,這些數據由另外一個模塊來負責處理(此處的模塊是廣義的,能夠是類、函數、線程、進程等)。產生數據的模塊,就形象地稱爲生產者;而處理數據的模塊,就稱爲消費者。 java

單單抽象出生產者和消費者,還夠不上是生產者/消費者模式。該模式還須要有一個緩衝區處於生產者和消費者之間,做爲一箇中介。生產者把數據放入緩衝區,而消費者從緩衝區取出數據。多線程

好處:併發

一、解耦 app

  假設生產者和消費者分別是兩個類。若是讓生產者直接調用消費者的某個方法,那麼生產者對於消費者就會產生依賴(也就是耦合)。未來若是消費者的代碼發生變化,可能會影響到生產者。而若是二者都依賴於某個緩衝區,二者之間不直接依賴,耦合也就相應下降了。 ide

二、支持併發函數

        使用了生產者/消費者模式以後,生產者和消費者能夠是兩個獨立的併發主體(常見併發類型有進程和線程兩種)。生產者把製造出來的數據往緩衝區一丟,就能夠再去生產下一個數據。基本上不用依賴消費者的處理速度。其實當初這個模式,主要就是用來處理併發問題的。 this

三、支持忙閒不均 
  緩衝區還有另外一個好處。若是製造數據的速度時快時慢,緩衝區的好處就體現出來了。當數據製造快的時候,消費者來不及處理,未處理的數據能夠暫時存在緩衝區中。等生產者的製造速度慢下來,消費者再慢慢處理掉。 線程

代碼實例:code

/**
 * 蘋果
 * @author Administrator
 */
public class Apple {

	private int id;
	private String descFlat;
	private String color;
	
	public Apple(int id, String descFlat, String color){
		this.id = id;
		this.descFlat = descFlat;
		this.color = color;
	}
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getDescFlat() {
		return descFlat;
	}
	public void setDescFlat(String descFlat) {
		this.descFlat = descFlat;
	}
	public String getColor() {
		return color;
	}
	public void setColor(String color) {
		this.color = color;
	}

	@Override
	public String toString() {
		return "Apple [id=" + id + ", descFlat=" + descFlat + ", color="
				+ color + "]";
	}
}
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * 定義籃子  - 多線程模擬實現生產者/消費者模型
 * @author Administrator
 */
public class Basket {

	BlockingQueue<Apple> queue = new LinkedBlockingQueue<Apple>();
	
	// 生產 蘋果  // put方法放入一個蘋果,若basket滿了,等到basket有位置
	public void produce(Apple apple){
		try {
			queue.put(apple); 
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	// 消費 蘋果   // take方法取出一個蘋果,若basket爲空,等到basket有蘋果爲止(獲取並移除此隊列的頭部)
	public Apple consume(){
		try {
			return queue.take();
		} catch (InterruptedException e) {
			e.printStackTrace();
			return null;
		}
	}
	
}
/**
 * 定義生產者
 * @author Administrator
 */
public class Producer implements Runnable{

	private int instance;
	private Basket basket;	
	private boolean flat;
	
    public Producer(int instance, Basket basket, boolean flat){
    	this.instance = instance;
    	this.basket = basket;
    	this.flat = flat;
    }
	
	public void run() {
		
		System.out.println("開始初始化生產" + instance + "蘋果");
		for(int i=0; i<instance; i++){
			Apple apple = new Apple(i,"描述"+i,"紅色");
			basket.produce(apple);
		}
		System.out.println("初始化生產了" + instance + "蘋果,完畢");
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
        while(flat){
        	if(basket.queue.size() < instance){
        		System.out.println("庫存不足,準備生產了" + instance + "蘋果");
        		for(int i=0; i<instance; i++){
        			Apple apple = new Apple(i,"描述"+i,"紅色");
        			basket.produce(apple);
        		}
        		System.out.println("已經生產了" + instance + "蘋果");
    		}
        	try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
        }
	}
}
/**
 * 消費者
 * @author Administrator
 */
public class Consumer implements Runnable{

    private int instance;
    private Basket basket;
    private boolean flat; 
    
    public Consumer(int instance, Basket basket, boolean flat){
    	this.instance = instance;
    	this.basket = basket;
    	this.flat = flat;
    }
	
	public void run() {
		
		while(flat){
			System.out.println("籃子中蘋果數量:" + basket.queue.size());
			if(basket.queue.size() >= instance){
				System.out.println("開始消費....");
				for(int i=0; i<instance; i++){
					Apple apple = basket.consume();
					if(apple != null){
						System.out.println(apple);
					}
				}
				System.out.println("消費....結束");
			}else{
				System.out.println("籃子中 蘋果不足...");
				try {
					Thread.sleep(1500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

}
public class BlockingQueueTest {

	public static void main(String[] args) {
		// 定義一個 籃子
		Basket basket = new Basket();
		
		int instance = 5;
		boolean flat = true;
		
		// 初始化 生產者
		Producer producer = new Producer(instance, basket,flat);
        new Thread(producer).start();
		
		// 初始化 消費者
		Consumer consumer = new Consumer(instance, basket, flat);
		new Thread(consumer).start();
	}
	
}
相關文章
相關標籤/搜索