對於多線程程序來講,無論任何編程語言,生產者和消費者模型都是最經典的。就像學習每一門編程語言同樣,Hello World!都是最經典的例子。java
實際上,準確說應該是「生產者-消費者-倉儲」模型,離開了倉儲,生產者消費者模型就顯得沒有說服力了。編程
對於此模型,應該明確一下幾點:多線程
一、生產者僅僅在倉儲未滿時候生產,倉滿則中止生產。編程語言
二、消費者僅僅在倉儲有產品時候才能消費,倉空則等待。ide
三、當消費者發現倉儲沒產品可消費時候會通知生產者生產。學習
四、生產者在生產出可消費產品時候,應該通知等待的消費者去消費。this
此模型將要結合java.lang.Object的wait與notify、notifyAll方法來實現以上的需求。這是很是重要的。 線程
注意:1.用while判斷而不用if,由於while能保證在等待中的線程被喚醒後可以先進行while判斷,若是是if則再也不判斷,會致使錯誤。code
2.用notifyAll而不用notify,由於notify僅通知相同類型的線程,這時,若是該類型線程處於等待則整個程序會產生死鎖;若是使用notifyAll則通知了全部線程,這樣總能有線程繼續運行下去,程序不會產生死鎖。blog
/** * * @author Yuanyuan */ public class TestCP { public static void main(String[] args) { Base b = new Base(20); Customer1 c1 = new Customer1(b, 10); Customer1 c2 = new Customer1(b,20); Customer1 c3 = new Customer1(b,20); Producer1 p1 = new Producer1(b, 10); c1.start(); c2.start(); c3.start(); p1.start(); } } class Base { private static final int total = 100; private int current; public Base(int initSize) { this.current = initSize; } public Base() { } public synchronized void produce(int size) { while (size > total - current) { System.out.println("要生產的產品量" + size + "超出了倉庫剩餘容量" + (total - current) + ",暫時沒法生產!"); try { this.wait(); } catch (Exception ex) { System.out.println(ex.getMessage()); ex.printStackTrace(); } } current = current + size; System.out.println("新生產了" + size + ",當前庫存" + current); this.notifyAll(); } public synchronized void custum(int size) { while (size > current) { System.out.println("要消費的產品量" + size + "超出了庫存" + current + ",暫時沒法消費!"); try { this.wait(); } catch (Exception ex) { System.out.println(ex.getMessage()); ex.printStackTrace(); } } current = current -size; System.out.println("新消費了"+size+"當前庫存"+current); this.notifyAll(); } } class Producer1 extends Thread { private Base b; private int size; public Producer1(Base b,int size) { this.b = b; this.size = size; } @Override public void run() { b.produce(size); } } class Customer1 extends Thread { private Base b; private int size; public Customer1(Base b, int size) { this.b = b; this.size = size; } @Override public void run() { b.custum(size); } }
運行結果:
新消費了10當前庫存10
新生產了10,當前庫存20
新消費了20當前庫存0
要消費的產品量20超出了庫存0,暫時沒法消費!