Java多线程(3)—生产者/消费者
這個是一個典型的線程問題。生成者(Productor)生產商品并交給店員(Clerk),消費者(Customer)從店員處購買商品,店員一次性只能購買固定數量的產品,如果生產者試圖生成更多的商品,店員會叫生產者暫停一下,如果店里倉庫有空位再通知生產者繼續生產,如果店中沒有商品了,就會告訴消費者等一下,如果店中有商品了就通知消費者來購買。這個場景和我們實際情況也比較貼切,這樣就會想可能存在如下問題:
在解決這個方法之前先介紹一下線程通信
所謂線程通信可以這樣理解:線程與線程之間不是相互獨立的個體,它們彼此之間需要相互通信和協作,最典型的例子就是生產者-消費者問題:當隊列滿時,生產者需要等待隊列有空間才能繼續往里面放入商品,而在等待的期間內,生產者必須釋放對臨界資源(即隊列)的占用權。因為生產者如果不釋放對臨界資源的占用權,那么消費者就無法消費隊列中的商品,就不會讓隊列有空間,那么生產者就會一直無限等待下去。因此一般情況下,當隊列滿時,會讓生產者交出對臨界資源的占用權,并進入掛起狀態。然后等待消費者消費了商品,然后消費者通知生產者隊列有空間了。同樣地,當隊列空時,消費者也必須等待,等待生產者通知它隊列中有商品了。這種互相通信的過程就是線程間的協作。
1.notify/wait
前面的文中通過包括 static?synchronized 等手段來解決數據共享的問題,即多個線程主動地讀取一個共享數據,通過 同步互斥訪問機制保證線程的安全性。等待/通知機制主要由Object類中的wait()、notify() 和 notifyAll()三個方法來實現。
wait():令當前線程掛起并放棄CPU、同步資源,讓其他線程可以訪問并修改共享資源,而當前現場排隊等候以獲得再次對資源的訪問機會
notify():喚醒正在排隊等待同步資源的線程中優先級最高者結束等待
notifyAll():喚醒正在排隊等待資源的所有線程結束等待。
注意:
輸出結果如下:
2.生產者/消費者
結合上述介紹的notify/wait機制,下面來實現生產者和消費者
package day15;public class Test3 {public static void main(String[] args) {Clerk c = new Clerk();//消費時不生產,生產時不消費//生產者new Thread(new Runnable() {@Overridepublic void run() {synchronized (c) {while (true) {//無限循環表示無限生產if (c.productNum == 0) {System.out.println("商品數為0,開始生產");while (c.productNum < 5) {c.productNum++;//生產之后,增加商品System.out.println("庫存值:"+c.productNum);}System.out.println("產品數為:" + c.productNum +"結束生產");c.notify();//喚醒消費者,讓生產者線程等待}else {try {c.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}}},"生產者").start();//消費時不生產,生產時不消費//生產者new Thread(new Runnable() {@Overridepublic void run() {synchronized (c) {while (true) {//無限循環表示無限消費if (c.productNum == 5) {System.out.println("商品數為4,開始消費");while (c.productNum > 0) {c.productNum--;//消費產品,產品減少System.out.println("庫存值:"+c.productNum);}System.out.println("產品數為:" + c.productNum +"結束消費");c.notify();//喚醒生產者,讓消費者線程等待}else {try {c.wait();//消費者線程等待} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}}},"消費者").start();} }class Clerk{public static int productNum = 0;}輸出結果如下:
?
?
?
?
?
?
總結
以上是生活随笔為你收集整理的Java多线程(3)—生产者/消费者的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java多线程(2)—线程同步
- 下一篇: JMeter初探四-Fiddler录制与