之前感覺很簡單,但是有一次面試讓我在紙上寫,居然沒寫對丟人啊。
生產者消費者問題(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();
}
}
結果如下: