1. 生產/消費者模型
生產/消費者問題是個非常典型的多線程問題,涉及到的對象包括“生產者”、“消 費者”、“倉庫”和“產品”。他們之間的關係如下:
(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\n", 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\n", 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); }}