生產(chǎn)者-消費(fèi)者(producer-consumer)問(wèn)題,兩個(gè)進(jìn)程共享一個(gè)公共的固定大小的緩沖區(qū)。其中一個(gè)是生產(chǎn)者,用于將消息放入緩沖區(qū);另外一個(gè)是消費(fèi)者,用于從緩沖區(qū)中取出消息。
這樣應(yīng)該是生產(chǎn)者生產(chǎn)一個(gè)產(chǎn)品,然后消費(fèi)者取走一個(gè)產(chǎn)品,然后再生產(chǎn)、再消費(fèi),這個(gè)看似很理所當(dāng)然的邏輯在現(xiàn)實(shí)中是必然的,但是在程序里卻出現(xiàn)了問(wèn)題。a:生產(chǎn)者生產(chǎn)了很多消費(fèi)者卻沒(méi)有取,b:生產(chǎn)這還沒(méi)有生產(chǎn)完一個(gè)完整的產(chǎn)品消費(fèi)者卻已經(jīng)取走了好幾次了,這樣取走的產(chǎn)品當(dāng)然是不合格的。
下面就用生產(chǎn)和消費(fèi)鞋子為例,看看程序是怎么運(yùn)行的吧.. .. ..

Demo01
package demo;
class Shoes{
// 鞋子類(lèi),兩個(gè)屬性:使用者(男/女),大小(大/小)
String user=null;
String size=null;
}
class Pro implements Runnable{
// 生產(chǎn)者,生產(chǎn)
Shoes shoe = null;
public Pro(Shoes s){
this.shoe=s;
}
public void run(){
int i=0;
while(true){
if(i==0){
// 男人穿的鞋子是大號(hào)的
shoe.user="男式";
shoe.size="大號(hào)";
i=1;
}else{
// 女人穿的鞋子是小號(hào)的
shoe.user="女式";
shoe.size="小號(hào)";
i=0;
}
}
}
}
class Cus implements Runnable{
Shoes shoe=null;
public Cus(Shoes s){
this.shoe=s;
}
public void run(){
while(true){
System.out.println(shoe.user+"-->"+shoe.size);
}
}
}
public class Demo01 {
/**生產(chǎn)者-消費(fèi)者問(wèn)題 producer-consumer
* @param args
*/
public static void main(String[] args) {
// 設(shè)置鞋子的一個(gè)生產(chǎn)者和一個(gè)消費(fèi)者,并啟動(dòng)兩個(gè)線程,分別進(jìn)行生產(chǎn)和消費(fèi)
Shoes shoe = new Shoes();
Pro p = new Pro(shoe);
Cus c = new Cus(shoe);
new Thread(p).start();
new Thread(c).start();
}
}
結(jié)果:
從結(jié)果中可以看到,第一次取時(shí)已經(jīng)生產(chǎn)完一雙男鞋,女鞋還沒(méi)有生產(chǎn)完就取走了女鞋,第二次到第四次消費(fèi)都是男鞋,看來(lái)是要么生產(chǎn)的太多了,沒(méi)有取走,要么就是取的太快,只生產(chǎn)了一雙男鞋卻取了四次。
這樣的程序顯然是不符合實(shí)際的,所以就要加以改進(jìn)。
應(yīng)該是生產(chǎn)時(shí),生產(chǎn)者進(jìn)入車(chē)間并把車(chē)間的門(mén)上鎖,生產(chǎn)一雙后生產(chǎn)者出來(lái),消費(fèi)者進(jìn)入到車(chē)間并把車(chē)間門(mén)上鎖,取到鞋子后出來(lái),這樣車(chē)間里只有一個(gè)人,要么生產(chǎn)者要么消費(fèi)者,這樣就可以保證生產(chǎn)合格的產(chǎn)品。
改進(jìn)的程序:

Demo02
package demo2;
class Shoes{
// 鞋子類(lèi),兩個(gè)屬性:使用者(男/女),大小(大/小)
String user=null;
String size=null;
private boolean flag = true;
public synchronized void set(String user,String size){
//如果flag的值不是true則要等待
if (!flag){
//等待
try{
wait();
}catch(Exception e){}
}
try{
Thread.sleep(100);
}catch (Exception e){}
// 如果向下繼續(xù)執(zhí)行了,則表示可以設(shè)置,flag = true
this.user = user;
this.size = size;
// 修改設(shè)置的標(biāo)志
flag = false;
//喚醒其他線程
notify();
}
//設(shè)置一個(gè)輸出方法
public synchronized void get(){
// 如果flag的值為true的時(shí)候,表示要等待
if(flag){
try{
wait();
}catch(Exception e){}
}
try{
Thread.sleep(100);
}catch (Exception e){}
//如果向下執(zhí)行了,則表示允許取出
System.out.println(this.user+" --> "+this.size);
//改變標(biāo)志,表示可以生產(chǎn)了
flag = true;
notify();
}
}
class Pro implements Runnable{
// 生產(chǎn)者,生產(chǎn)
Shoes shoe = null;
public Pro(Shoes s){
this.shoe=s;
}
public void run(){
int i=0;
while(true){
if(i==0){
// 男人穿的鞋子是大號(hào)的
shoe.set("男式", "大號(hào)");
i=1;
}else{
// 女人穿的鞋子是小號(hào)的
shoe.set("女式", "小號(hào)");
i=0;
}
}
}
}
class Cus implements Runnable{
Shoes shoe=null;
public Cus(Shoes s){
this.shoe = s;
}
public void run(){
while(true){
shoe.get();
}
}
}
public class Demo02 {
/**生產(chǎn)者-消費(fèi)者問(wèn)題 producer-consumer
* @param args
*/
public static void main(String[] args) {
// 設(shè)置鞋子的一個(gè)生產(chǎn)者和一個(gè)消費(fèi)者,并啟動(dòng)兩個(gè)線程,分別進(jìn)行生產(chǎn)和消費(fèi)
Shoes shoe = new Shoes();
Pro p = new Pro(shoe);
Cus c = new Cus(shoe);
new Thread(p).start();
new Thread(c).start();
}
}
運(yùn)行結(jié)果:

posted on 2010-11-12 23:30
Mineralwasser 閱讀(252)
評(píng)論(0) 編輯 收藏