Producer Consumer模式与 Guarded Suspension 模式 是类似的,只不过Guarded Suspension模式并不限制缓冲区的长度,Producer Consumer模式假设所生产的产品放置在一个长度有限制的缓冲区(就像是一个产品桌,它可以摆放的空间是有限的),如果缓冲区满了,则生产者必须停止继续将产品放到缓冲区中,直到消费者取走了产品而有了空间,而如果缓冲区中没有产品,当然消费者必须等待,直到有新的产品放到缓冲区中。
import java.util.LinkedList; public class ProductTable { private LinkedList products = new LinkedList(); public synchronized void addProduct(Product product) { while(products.size() >= 2) { // 容量限制为 2 try { wait(); } catch(InterruptedException e) {} } products.addLast(product); notifyAll(); } public synchronized Product getProduct() { while(products.size() <= 0) { try { wait(); } catch(InterruptedException e) {} } Product product = (Product) products.removeFirst(); notifyAll(); return product; } }
以下举一个最简单的:生产者每次生产一个整数并放置在桌子上,而消费者消耗整数,桌子上一次只能放置一个整数,如果桌子上已有整数,则生产者等待消费者将整数消耗并通知生产者生产下一个整数,如果桌子上没有整数,则消费者等待生产者生产整数并通知消费者可以消耗整数。
public class Producer extends Thread { private ProductTable productTable; public Producer(ProductTable productTable) { this.productTable = productTable; } public void run() { System.out.println("Produce integer......"); for(int product = 1; product <= 10; product++) { try { // wait for a random time Thread.sleep((int) Math.random() * 3000); } catch(InterruptedException e) { e.printStackTrace(); } productTable.setIntProduct(product); } } }
public class Consumer extends Thread { private ProductTable productTable; public Consumer(ProductTable productTable) { this.productTable = productTable; } public void run() { for(int i = 1; i <= 10; i++) { try { // wait for a random time Thread.sleep((int) (Math.random() * 3000)); } catch(InterruptedException e) { e.printStackTrace(); } productTable.getProductInt(); } } }
生产者将产品放至桌上,而消费者将产品从桌上取走,所以桌子是个维护是否让被放置或消耗产品的地方,由它来决定谁必须等待与通知:
public class ProductTable { private int productInt = -1; // -1 for no product public synchronized void setIntProduct(int product) { if(productInt != -1) { try { wait(); } catch(InterruptedException e) { e.printStackTrace(); } } productInt = product; System.out.println("set (" + product + ")"); notify(); } public synchronized int getProductInt() { if(productInt == -1) { try { wait(); } catch(InterruptedException e) { e.printStackTrace(); } } int p = productInt; System.out.println("Get (" + productInt + ")"); productInt = -1; notify(); return p; } }
生产者会生产10个整数,而消费者会消耗10个整数,由于桌上只能放置一个整数,所以每生产一个就消耗一个。