生產者與消費者的兩種方式

2021-10-06 21:37:34 字數 3275 閱讀 2166

synchronized版,使用wait、notify

public class demo01  catch (interruptedexception e) 

}},"生產者").start();

//消費者a去購買商品

new thread(()-> catch (interruptedexception e)

}},"消費者a").start();

//消費者b去購買商品

new thread(()-> catch (interruptedexception e)

}},"消費者b").start()

}}class shop

goodsnum -= num;

system.out.println(thread.currentthread().getname()+"買走了"+num+"件商品,還剩餘"+goodsnum+"件商品");

this.notifyall();

}public synchronized void buygoods(int num) throws interruptedexception

goodsnum += num;

system.out.println(thread.currentthread().getname()+"送來了"+num+"件商品,還剩餘"+goodsnum+"件商品");

this.notifyall();

}}

有可能出現的問題:虛假喚醒

表現:

虛假喚醒的表現為: 有時候資源會出現"超賣"現象. 也就是出現負數, 而這是不應該出現的. 關鍵點就是判斷合法性的時候, 使用了if進行判斷.

過程:

- 在消費者進入到購買方法中時,會告知商品為0,發生阻塞(wait)會將鎖釋放,這是其他消費執行緒也進入,發生阻塞,等到生產者將商品補充之後,再去進行商品的購買(num--),這時if只會判斷一次,所以就可能發生num=-1;

解決辦法:

將if換成while

使用lock鎖和 condition

獲取condition的方法:

lock lock = new reentrantlock();

condition condition1 = lock.newcondition();

condition主要方法:

public class test01 

},"執行緒a").start();

new thread(()->

},"執行緒b").start();

new thread(()->

},"執行緒c").start();

new thread(()->

},"執行緒d").start();

}}class a

num++;

system.out.println(thread.currentthread().getname()+"->"+num);

condition.signalall();//喚醒

} catch (exception e) finally

}public synchronized void decrement()

num--;

system.out.println(thread.currentthread().getname()+"->"+num);

condition.signalall();

} catch (exception e) finally

}}

使用condition精準通知和喚醒執行緒:

//有三個方法:

public void printa(){}//執行緒a執行

public void printb(){}//執行緒b執行

public void printc(){}//執行緒c執行

private condition condition1 = lock.newcondition();//監聽執行緒a

private condition condition2 = lock.newcondition();//監聽執行緒b

private condition condition3 = lock.newcondition();//監聽執行緒c

//在printa方法執行完之後,用condition2去喚醒執行緒b執行priintb

//在printb方法執行完之後,用condition3去喚醒執行緒b執行priintc

//在printa方法執行完之後,用condition1去喚醒執行緒b執行priinta

//可以達到condition精準的通知和喚醒執行緒

具體操作**:

/**

* a執行完呼叫b,b執行完呼叫c c執行完呼叫a

*/public class test02

},"a").start();

//執行緒b

new thread(()->

},"b").start();

//執行緒c

new thread(()->

},"c").start();

}}class data1

num=2;

//通知condition2去喚醒執行緒b

condition2.signal();

system.out.println(thread.currentthread().getname()+":->aaaa");

} catch (exception e) finally

}public void printb()

num = 3;

//通知condition3去喚醒執行緒c

condition3.signal();

system.out.println(thread.currentthread().getname()+":->bbbb");

} catch (exception e) finally

}public void printc()

num = 1;

//通知condition1去喚醒執行緒a

condition1.signal();

system.out.println(thread.currentthread().getname()+":->cccc");

} catch (exception e) finally

}}

生產者消費者 生產者與消費者模式

一 什麼是生產者與消費者模式 其實生產者與消費者模式就是乙個多執行緒併發協作的模式,在這個模式中呢,一部分執行緒被用於去生產資料,另一部分執行緒去處理資料,於是便有了形象的生產者與消費者了。而為了更好的優化生產者與消費者的關係,便設立乙個緩衝區,也就相當於乙個資料倉儲,當生產者生產資料時鎖住倉庫,不...

生產者消費者問題的兩種寫法

問題 乙個固定容量的同步容器,有get方法和put方法,和size 方法。n個生產者不斷往裡面put,m個消費者不斷從中get。方式一 object的wait和notify public class testpandc p i t.start try catch interruptedexcepti...

生產者與消費者

include include include include include include define size of buffer 10 int buffer size of buffer 緩衝陣列 int in 0,out 0 採用迴圈佇列方式進行陣列的訪問 宣告訊號量 sem t ful...