生产者消费者问题,又称有限缓冲区问题。要解决两个问题:
1、对缓冲区中资源进行同步(存和取)
2、当缓冲区满时,不可存,生产者需要等待;当缓冲区空时,不可取,消费者需要等待
解决方法:
对于问题1: 对存取方法加同步synchronized
对于问题2:通过线程的等待和唤醒实现
直接看代码吧
主要有四个类:商品,缓冲区,生产者,消费者
1、商品类
class Product {
private int productId = 0;
public Product(int productId) {
this.productId = productId;
}
public int getProductId() {
return productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
}
2、缓冲区
class Buffer {
private int base = 0;
private int top = 0;
// 缓冲区大小
private Product[] products = new Product[10];
/**
* 生产产品
*
* @param product
*/
public synchronized void push(Product product) {
if (top == products.length) { // 如果缓冲区已满,等待消费
try {
System.out.println("缓冲区已满,正在等待消费..");
super.wait();
} catch (InterruptedException e) {
System.out.println("stop push product because other reasons");
}
}
// 缓冲区未满,将生产的产品入库
products[top] = product;
// 库中产品数量+1
top++;
super.notify();
}
public synchronized Product pop() {
Product product = null;
while (top == base) { // 缓冲区空,不能消费
notify();
try {
System.out.println("缓冲区已空,正等待生产...");
super.wait();
} catch (InterruptedException e) {
System.out.println("stop push product because other reasons");
}
}
// 缓冲区不空,可以消费
top--;
product = products[top];
products[top] = null;
super.notify();
return product;
}
}
3、生产者
class Producer implements Runnable {
private String producerName;
private Buffer Buffer;
public Producer(String producerName, Buffer Buffer) {
this.producerName = producerName;
this.Buffer = Buffer;
}
public void setProducerName(String producerName) {
this.producerName = producerName;
}
public String getProducerName() {
return producerName;
}
@Override
public void run() {
execProcuct();
}
private void execProcuct() {
int i = 0;
while (true) {
i++;
Product pro = new Product(i);
Buffer.push(pro);
System.out.println(getProducerName() + " 生产了 : " + pro.getProductId());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
return;
}
}
}
}
4、消费者
class Consumer implements Runnable {
private String consumerName = null;
private Buffer Buffer = null;
public Consumer(String consumerName, Buffer Buffer) {
this.consumerName = consumerName;
this.Buffer = Buffer;
}
public void setConsumerName(String consumerName) {
this.consumerName = consumerName;
}
public String getConsumerName() {
return consumerName;
}
public void execConsume() {
while (true) {
System.out.println(getConsumerName() + " 消费了 :" + Buffer.pop().getProductId());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
return;
}
}
}
@Override
public void run() {
execConsume();
}
}
5、入口
public class ProducerConsumer {
public static void main(String[] args) {
Buffer Buffer = new Buffer();
Producer producer = new Producer("+++生产者", Buffer);
Consumer comsumer = new Consumer("-消费者", Buffer);
Thread t1 = new Thread(producer);
Thread t2 = new Thread(comsumer);
t1.start();
t2.start();
}
}
参考:
http://www.cnblogs.com/rollenholt/archive/2011/08/28/2156357.html
http://www.cnblogs.com/dennisit/archive/2013/02/25/2931573.html
http://blog.chinaunix.net/uid-21411227-id-1826740.html
特此声明。