之前感觉很简单,但是有一次面试让我在纸上写,居然没写对丢人啊。
生产者消费者问题(Producer-consumer problem):生产者不断地生产产品,消费者取走生产者生产的产品。生产者生产出产品后将其放到一个区域之中,消费者从这个地方去除数据。
涉及的问题:要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。
主要涉及:多线程的同步问题。
1、假设生产者线程刚向数据存储空间添加了产品的名称,还没有添加产品的内容,程序就切到了消费者的线程,消费这的
线程将吧产品的名称和上一个产品的内容联系到了一起。
2、生产者放了若干次的产品,消费者才开始取产品,或者是,消费者去玩一个产品后,还没等待生产者生产新的产品,有
重复的去除已经去过的产品。
其生产者消费者问题程序实现如下:
一、产品:
package andy.thread.test;
/**
* @author andy
* @version:2015-3-20 上午10:09:42
*
*
*/
public class Product {
private String pName;
private String pContent;
private boolean flag; // 此为产品的标记 true为已有产品 false为没有产品
//生产
public synchronized void put(String pName, String pContent) {
if (flag) {// 如果有产品,等待消费
try {
super.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.setpName(pName);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.setpContent(pContent);
System.out.println("生产产品");
this.flag = true; // 标记为以生产,唤醒消费
super.notify();
}
//消费
public synchronized void romve() {
if (!flag) { // 没有产品时等待
try {
super.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out
.println("消费:" + this.getpName() + "---" + this.getpContent());
this.flag = false; // 已消费,可以进行生产了
super.notify();
}
public String getpName() {
return pName;
}
public void setpName(String pName) {
this.pName = pName;
}
public String getpContent() {
return pContent;
}
public void setpContent(String pContent) {
this.pContent = pContent;
}
}
二、生产者
package andy.thread.test;
import java.util.concurrent.TimeUnit;
/**
* @author andy
* @version:2015-3-20 上午11:05:53
*
*
*/
public class Producer implements Runnable {
private Product product = null;
public Producer(Product product) {
this.product = product;
}
@Override
public void run() {
for (int i = 0; i < 50; i++) {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
product.put("产品" + i, i + "");
}
}
}
三、消费者
package andy.thread.test;
import java.util.concurrent.TimeUnit;
/**
* @author andy
* @version:2015-3-20 上午10:56:18
*
*
*/
public class Consumer implements Runnable{
private Product product = null;
public Consumer(Product product){
this.product = product;
}
@Override
public void run() {
for (int i = 0; i < 50; i++) {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.product.romve();
}
}
}
测试:
package andy.thread.test;
/**
* @author andy
* @version:2015-3-20 上午11:12:25
*
*
*/
public class ConsumerProducerTest {
/**
* @param args
*/
public static void main(String[] args) {
Product product = new Product();
Producer producer = new Producer(product);
Consumer consumer = new Consumer(product);
new Thread(producer).start();
new Thread(consumer).start();
}
}
结果如下: