Java多線程--生產者與消費者問題

來源:互聯網
上載者:User

標籤:多線程   生產者與消費者   

說明

Java中,線程之間的通訊主要是由java.lang.Object類提供的wait、notify和notifyAll這3個方法來完成:

①對象的wait方法被調用後,線程進入對象的等待隊列中,並釋放對象鎖,其它線程可以競爭使用此對象鎖;sleep方法使得一個線程進入睡眠狀態,但是線程所佔有的資源並沒有釋放。

②當對象的notify方法被調用,該方法會從對象的等待隊列中隨機取出一個線程來喚醒;notifyAll是喚醒等待隊列中所有線程,這些線程會與其它正在執行的線程共同競爭對象鎖。

③wait、notify和notifyAll這3個方法只能出現在synchronized作用的範圍內。當多個線程等待同一對象,而它們等待等待的條件不同時,應該使用notifyAll方法。notifyAll會導致效能下降,因為不必要的線程也會被喚醒。而notify喚醒的線程有可能不是所期望的線程。


生產者與消費者問題

這裡,將使用某類資源(用類Goods表示)的線程稱為消費者Consumer,產生同類資源的線程稱為Producer。要想使得Consumer和Producer能夠協同工作,則它們應該遵循如下規則:

(1)只要緩衝區buffer有空間,生產者Producer就可向其中存放資源;當緩衝區buffer已滿時,則讓生產者Producer等待,放棄自己已擷取的對象鎖,進入等待隊列;

(2)只要緩衝區中有資源可用,消費者Consumer就可以從buffer中取出資源;當buffer為空白時,則讓Consumer等待,放棄自己已擷取的對象鎖,進入等待隊列;

(3)Producer和Consumer不能同時讀、寫buffer。所以對buffer進行操作的方法increase(生產資源)和decrease(消費資源)均需要使用synchronized進行同步。


/** * Goods類,表示共用資源 */package com.hh.Producer.Consumer;public class Goods {private final int SIZE = 5;private int buffer = 0;/** * 共用資源增加 */public synchronized int increase() {if (buffer < SIZE) {++buffer;notify(); // 通知消費者可以消費} else {try {wait(); // 產生者線程等待,直到消費者線程發出notify通知} catch (InterruptedException e) {e.printStackTrace();}}return buffer;}/** * 共用資源減少 */public synchronized int decrease() {if (buffer > 0) {--buffer;notify(); // 通知生產者可以生產} else {try {wait(); // 消費者線程等待,直到生產者線程發出notify通知} catch (InterruptedException e) {e.printStackTrace();}}return buffer;}public int getGoodsSize() {return SIZE;}}


/** * Producer類,類比生產者線程 */package com.hh.Producer.Consumer;public class Producer implements Runnable {private Goods goods;public Producer(Goods goods) {this.goods = goods;}@Overridepublic void run() {while (true) {int goodsCount = goods.increase();if (goodsCount != goods.getGoodsSize()) {System.out.println("生產者生產了一件商品,目前商品數:" + goodsCount);} else {System.out.println("商品已滿,生產者等待");}try {Thread.sleep((int) (Math.random() * 1000));} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}

/** * Consumer類,類比消費者 */package com.hh.Producer.Consumer;public class Consumer implements Runnable {private Goods goods;public Consumer(Goods goods) {this.goods = goods;}@Overridepublic void run() {while (true) {int goodsCount = goods.decrease();if (goodsCount != 0) {System.out.println("消費者消費了一件商品,目前商品數:" + goodsCount);} else {System.out.println("商品已空,消費者等待");}try {Thread.sleep((int) (Math.random() * 1000));} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}

/** * 測試生產者Producer與消費者Consumer線程之間的通訊 */package com.hh.Producer.Consumer;public class TestMain {public static void main(String[] args) {Goods goods = new Goods();Producer producer = new Producer(goods);Consumer consumer = new Consumer(goods);new Thread(producer).start();new Thread(consumer).start();}}

注意:是在共用資源Goods類中進行wait和notify操作,並不是在Producer或者Consumer類中。

對於這樣的問題,一定要自己動手寫範例代碼,這樣才能較好的理解線程之間的通訊問題。


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.