對於多執行緒程式來說,不管任何程式語言,生產者和消費者模型都是最經典的。就像學習每一門程式語言一樣,Hello World!都是最經典的例子。
實際上,準確說應該是“生產者-消費者-倉儲”模型,離開了倉儲,生產者消費者模型就顯得沒有說服力了。
對於此模型,應該明確一下幾點:
1、生產者僅僅在倉儲未滿時候生產,倉滿則停止生產。
2、消費者僅僅在倉儲有產品時候才能消費,倉空則等待。
3、當消費者發現倉儲沒產品可消費時候會通知生產者生產。
4、生產者在生產出可消費產品時候,應該通知等待的消費者去消費。
package cn.thread; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; /** * java多執行緒模擬生產者消費者問題 * * ProducerConsumer是主類,Producer生產者,Consumer消費者,Product產品,Storage倉庫 * * @author 林計欽 * @version 1.0 2013-7-24 下午04:49:02 */ public class ProducerConsumer { public static void main(String[] args) { ProducerConsumer pc = new ProducerConsumer(); Storage s = pc.new Storage(); ExecutorService service = Executors.newCachedThreadPool(); Producer p = pc.new Producer("張三", s); Producer p2 = pc.new Producer("李四", s); Consumer c = pc.new Consumer("王五", s); Consumer c2 = pc.new Consumer("老劉", s); Consumer c3 = pc.new Consumer("老林", s); service.submit(p); //service.submit(p2); service.submit(c); service.submit(c2); service.submit(c3); } /** * 消費者 * * @author 林計欽 * @version 1.0 2013-7-24 下午04:53:30 */ class Consumer implements Runnable { private String name; private Storage s = null; public Consumer(String name, Storage s) { this.name = name; this.s = s; } public void run() { try { while (true) { System.out.println(name + "準備消費產品."); Product product = s.pop(); System.out.println(name + "已消費(" + product.toString() + ")."); System.out.println("==============="); Thread.sleep(500); } } catch (InterruptedException e) { e.printStackTrace(); } } } /** * 生產者 * * @author 林計欽 * @version 1.0 2013-7-24 下午04:53:44 */ class Producer implements Runnable { private String name; private Storage s = null; public Producer(String name, Storage s) { this.name = name; this.s = s; } public void run() { try { while (true) { Product product = new Product((int) (Math.random() * 10000)); // 產生0~9999隨機整數 System.out.println(name + "準備生產(" + product.toString() + ")."); s.push(product); System.out.println(name + "已生產(" + product.toString() + ")."); System.out.println("==============="); Thread.sleep(500); } } catch (InterruptedException e1) { e1.printStackTrace(); } } } /** * 倉庫,用來存放產品 * * @author 林計欽 * @version 1.0 2013-7-24 下午04:54:16 */ public class Storage { BlockingQueue<Product> queues = new LinkedBlockingQueue<Product>(10); /** * 生產 * * @param p * 產品 * @throws InterruptedException */ public void push(Product p) throws InterruptedException { queues.put(p); } /** * 消費 * * @return 產品 * @throws InterruptedException */ public Product pop() throws InterruptedException { return queues.take(); } } /** * 產品 * * @author 林計欽 * @version 1.0 2013-7-24 下午04:54:04 */ public class Product { private int id; public Product(int id) { this.id = id; } public String toString() {// 重寫toString方法 return "產品:" + this.id; } } }
張三準備生產(產品:3359). 張三已生產(產品:3359). =============== 老劉準備消費產品. 王五已消費(產品:3359). =============== 王五準備消費產品. 張三準備生產(產品:1863). 張三已生產(產品:1863). =============== 老林已消費(產品:1863). =============== 老林準備消費產品. 張三準備生產(產品:5424). 張三已生產(產品:5424). 老劉已消費(產品:5424). =============== =============== 張三準備生產(產品:6290). 張三已生產(產品:6290). =============== 老劉準備消費產品. 王五已消費(產品:6290). =============== 張三準備生產(產品:990). 張三已生產(產品:990). =============== 老林已消費(產品:990). =============== 王五準備消費產品. 張三準備生產(產品:1971). 老林準備消費產品. 老劉已消費(產品:1971). =============== 張三已生產(產品:1971). =============== 張三準備生產(產品:5622). 老劉準備消費產品. 張三已生產(產品:5622). =============== 王五已消費(產品:5622). =============== 王五準備消費產品. 張三準備生產(產品:6570). 張三已生產(產品:6570). =============== 老林已消費(產品:6570). =============== 老林準備消費產品. 張三準備生產(產品:17). 老劉已消費(產品:17). =============== 張三已生產(產品:17). =============== 老劉準備消費產品. 張三準備生產(產品:7962). 張三已生產(產品:7962). =============== 王五已消費(產品:7962). =============== 王五準備消費產品. 張三準備生產(產品:3200). 張三已生產(產品:3200). =============== 老林已消費(產品:3200). =============== 老林準備消費產品. 張三準備生產(產品:7234). 張三已生產(產品:7234). =============== 老劉已消費(產品:7234). =============== 老劉準備消費產品. 張三準備生產(產品:6486). 張三已生產(產品:6486). =============== 王五已消費(產品:6486). =============== 張三準備生產(產品:5436). 王五準備消費產品. 王五已消費(產品:5436). ===============