📄 producerconsumer.htm
字号:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<link rel="stylesheet" href="css/stdlayout.css" type="text/css">
<link rel="stylesheet" href="css/print.css" type="text/css">
<meta content="text/html; charset=gb2312" http-equiv="content-type">
<title>Producer Consumer 模式</title>
</head>
<body>
<h3><a href="http://caterpillar.onlyfun.net/GossipCN/index.html">From
Gossip@caterpillar</a></h3>
<h1><a href="CppGossip.html">Design Pattern: Producer Consumer 模式</a></h1>
Producer Consumer模式与 <a href="GuardedSuspension.htm">Guarded Suspension 模式</a>
是类似的,只不过Guarded Suspension模式并不限制缓冲区的长度,Producer
Consumer模式假设所生产的产品放置在一个长度有限制的缓冲区(就像是一个产品桌,它可以摆放的空间是有限的),如果缓冲区满了,则生产者必须停止
继续将产品放到缓冲区中,直到消费者取走了产品而有了空间,而如果缓冲区中没有产品,当然消费者必须等待,直到有新的产品放到缓冲区中。 <br>
<br>
一个简单的 UML 顺序图如下所示:<br>
<div style="text-align: center;"><img style="width: 642px; height: 526px;" alt="ProducerConsumer" title="ProducerConsumer" src="images/producerConsumer.jpg"><br>
</div>
简单来说,Producer Consumer模式就像是加上了双重防护与等待的Guarded Suspension模式,而它的两个防护与等待的条件洽好相反,一个用Java实现的简单流程架构如下:<br>
<ul>
<li>ProductTable.java</li>
</ul>
<pre>import java.util.LinkedList;<br><br>public class ProductTable {<br> private LinkedList products = new LinkedList();<br><br> public synchronized void addProduct(Product product) {<br> while(products.size() >= 2) { // 容量限制为 2<br> try {<br> wait();<br> }<br> catch(InterruptedException e) {}<br> }<br><br> products.addLast(product);<br> notifyAll();<br> }<br> <br> public synchronized Product getProduct() {<br> while(products.size() <= 0) {<br> try {<br> wait();<br> }<br> catch(InterruptedException e) {}<br> }<br><br> Product product = (Product) products.removeFirst();<br> notifyAll();<br> <br> return product;<br> }<br>} </pre>
<br>
以下举一个最简单的:生产者每次生产一个整数并放置在桌子上,而消费者消耗整数,桌子上一次只能放置一个整数,如果桌子上已有整数,则生产者等待消费者将
整数消耗并通知生产者生产下一个整数,如果桌子上没有整数,则消费者等待生产者生产整数并通知消费者可以消耗整数。<br>
<ul>
<li>Producer.java
</li>
</ul>
<pre>public class Producer extends Thread {<br> private ProductTable productTable;<br> <br> public Producer(ProductTable productTable) {<br> this.productTable = productTable;<br> }<br> <br> public void run() {<br> System.out.println("Produce integer......");<br> for(int product = 1; product <= 10; product++) {<br> try {<br> // wait for a random time<br> Thread.sleep((int) Math.random() * 3000);<br> }<br> catch(InterruptedException e) {<br> e.printStackTrace();<br> }<br> productTable.setIntProduct(product);<br> } <br> }<br>} <br></pre>
<br>
<ul>
<li> Consumer.java
</li>
</ul>
<pre>public class Consumer extends Thread {<br> private ProductTable productTable;<br> <br> public Consumer(ProductTable productTable) {<br> this.productTable = productTable;<br> }<br> <br> public void run() {<br> for(int i = 1; i <= 10; i++) {<br> try {<br> // wait for a random time<br> Thread.sleep((int) (Math.random() * 3000));<br> }<br> catch(InterruptedException e) {<br> e.printStackTrace();<br> }<br> productTable.getProductInt();<br> }<br> }<br>} <br></pre>
<p></p>
生产者将产品放至桌上,而消费者将产品从桌上取走,所以桌子是个维护是否让被放置或消耗产品的地方,由它来决定谁必须等待与通知:
<ul>
<li> ProductTable.java
</li>
</ul>
<pre>public class ProductTable {<br> private int productInt = -1; // -1 for no product<br><br> public synchronized void setIntProduct(int product) {<br> if(productInt != -1) {<br> try {<br> wait();<br> }<br> catch(InterruptedException e) {<br> e.printStackTrace();<br> }<br> }<br><br> productInt = product;<br> System.out.println("set (" + product + ")");<br> notify();<br> }<br> <br> public synchronized int getProductInt() {<br> if(productInt == -1) {<br> try {<br> wait();<br> }<br> catch(InterruptedException e) {<br> e.printStackTrace();<br> }<br> }<br><br> int p = productInt;<br> System.out.println("Get (" + productInt + ")");<br> productInt = -1;<br> <br> notify();<br> <br> return p;<br> }<br>} <br></pre>
<br>
生产者会生产10个整数,而消费者会消耗10个整数,由于桌上只能放置一个整数,所以每生产一个就消耗一个。<br>
<br>
<br>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -