Java并發(fā)編程中的生產(chǎn)者與消費(fèi)者模型簡(jiǎn)述
概述
對(duì)于多線程程序來(lái)說(shuō),生產(chǎn)者和消費(fèi)者模型是非常經(jīng)典的模型。更加準(zhǔn)確的說(shuō),應(yīng)該叫“生產(chǎn)者-消費(fèi)者-倉(cāng)庫(kù)模型”。離開(kāi)了倉(cāng)庫(kù),生產(chǎn)者、消費(fèi)者就缺少了共用的存儲(chǔ)空間,也就不存在并非協(xié)作的問(wèn)題了。
示例
定義一個(gè)場(chǎng)景。一個(gè)倉(cāng)庫(kù)只允許存放10件商品,生產(chǎn)者每次可以向其中放入一個(gè)商品,消費(fèi)者可以每次從其中取出一個(gè)商品。同時(shí),需要注意以下4點(diǎn):
1. 同一時(shí)間內(nèi)只能有一個(gè)生產(chǎn)者生產(chǎn),生產(chǎn)方法需要加鎖synchronized。
2. 同一時(shí)間內(nèi)只能有一個(gè)消費(fèi)者消費(fèi),消費(fèi)方法需要加鎖synchronized。
3. 倉(cāng)庫(kù)為空時(shí),消費(fèi)者不能繼續(xù)消費(fèi)。消費(fèi)者消費(fèi)前需要循環(huán)判斷當(dāng)前倉(cāng)庫(kù)狀態(tài)是否為空,空的話則消費(fèi)線程需要wait,釋放鎖允許其他同步方法執(zhí)行。
4. 倉(cāng)庫(kù)為滿時(shí),生產(chǎn)者不能繼續(xù)生產(chǎn),生產(chǎn)者生產(chǎn)錢需要循環(huán)判斷當(dāng)前倉(cāng)庫(kù)狀態(tài)是否為滿,滿的話則生產(chǎn)線程需要wait,釋放鎖允許其他同步方法執(zhí)行。
示例代碼如下:
public class Concurrence { public static void main(String[] args) { WareHouse wareHouse = new WareHouse(); Producer producer = new Producer(wareHouse); Consumer consumer = new Consumer(wareHouse); new Thread(producer).start(); new Thread(consumer).start(); } } class WareHouse { private static final int STORE_SIZE = 10; private String[] storeProducts = new String[STORE_SIZE]; private int index = 0; public void pushProduct(String product) { synchronized (this) { while (index == STORE_SIZE) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } storeProducts[index++] = product; this.notify(); System.out.println("生產(chǎn)了: " + product + " , 目前倉(cāng)庫(kù)里共: " + index + " 個(gè)貨物"); } } public synchronized String getProduct() { synchronized (this) { while (index == 0) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } String product = storeProducts[index - 1]; index--; System.out.println("消費(fèi)了: " + product + ", 目前倉(cāng)庫(kù)里共: " + index + " 個(gè)貨物"); this.notify(); return product; } } } class Producer implements Runnable { WareHouse wareHouse; public Producer(WareHouse wh) { this.wareHouse = wh; } @Override public void run() { for (int i = 0; i < 40; i++) { String product = "product" + i; this.wareHouse.pushProduct(product); } } } class Consumer implements Runnable { WareHouse wareHouse; public Consumer(WareHouse wh) { this.wareHouse = wh; } @Override public void run() { for (int i = 0; i < 40; i++) { this.wareHouse.getProduct(); } } }
相關(guān)文章
java調(diào)用Oracle存儲(chǔ)過(guò)程的方法實(shí)例
這篇文章介紹了java調(diào)用Oracle存儲(chǔ)過(guò)程的方法實(shí)例,有需要的朋友可以參考一下2013-09-09一文詳解Redisson分布式鎖底層實(shí)現(xiàn)原理
這篇文章主要詳細(xì)介紹了Redisson分布式鎖底層實(shí)現(xiàn)原理,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07Java Vector和ArrayList的異同分析及實(shí)例講解
在本篇文章里小編給大家整理的是一篇關(guān)于Java Vector和ArrayList的異同分析及實(shí)例講解內(nèi)容,有興趣的朋友們可以學(xué)習(xí)參考下。2021-01-01利用Java簡(jiǎn)單實(shí)現(xiàn)一個(gè)代碼行數(shù)統(tǒng)計(jì)器方法實(shí)例
這篇文章主要給大家介紹了關(guān)于如何利用Java簡(jiǎn)單實(shí)現(xiàn)一個(gè)代碼行數(shù)統(tǒng)計(jì)器的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11Spring使用Jackson實(shí)現(xiàn)轉(zhuǎn)換XML與Java對(duì)象
這篇文章主要為大家詳細(xì)介紹了Spring如何使用Jackson實(shí)現(xiàn)轉(zhuǎn)換XML與Java對(duì)象,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-02-02Spring?Boot整合ELK實(shí)現(xiàn)日志采集與監(jiān)控
這篇文章主要介紹了Spring?Boot整合ELK實(shí)現(xiàn)日志采集與監(jiān)控,需要的朋友可以參考下2022-06-06