生產(chǎn)者和消費者模型-隊列

隊列(進程通信ipc)

隊列主要用于解決進程間通信的問題谒兄,隊列底層就是通過管道和鎖的方式實現(xiàn)的舷嗡。

代碼示例:

from multiprocessing import Queue
import time

q=Queue(3)    # 指定隊列的長度

#隊列相關(guān)的操作方法
# put,get,put_nowait,get_nowait,full,empty
q.put(3)      # 向隊列中存放數(shù)據(jù),可以是任何類型的數(shù)據(jù)
q.put(3)
q.put(3)
print(q.full())   # 如果隊列滿绳瘟,則返回 True, 否則返回 False

print(q.get())    # 依次取出數(shù)據(jù)
print(q.get())
print(q.get())
print(q.empty())  # 如果隊列為空易茬,則返回True,否則返回 False

主要方法

  • q.put(): 用以插入數(shù)據(jù)到隊列中,put方法還有兩個可選參數(shù):blocked和timeout树埠。如果blocked為True(默認值)糠馆,并且timeout為正值,該方法會阻塞timeout指定的時間怎憋,直到該隊列有剩余的空間又碌。如果超時,會拋出Queue.Full異常绊袋。如果blocked為False毕匀,但該Queue已滿,會立即拋出Queue.Full異常
  • q.get方法可以從隊列讀取并且刪除一個元素癌别。同樣皂岔,get方法有兩個可選參數(shù):blocked和timeout。如果blocked為True(默認值)展姐,并且timeout為正值躁垛,那么在等待時間內(nèi)沒有取到任何元素,會拋出Queue.Empty異常圾笨。如果blocked為False教馆,有兩種情況存在,如果Queue有一個值可用擂达,則立即返回該值土铺,否則,如果隊列為空板鬓,則立即拋出Queue.Empty異常
  • q.get_nowait():同q.get(False)
  • q.put_nowait():同q.put(False)
  • q.empty():調(diào)用此方法時q為空則返回True悲敷,該結(jié)果不可靠,比如在返回True的過程中俭令,如果隊列中又加入了項目
  • q.full():調(diào)用此方法時q已滿則返回True后德,該結(jié)果不可靠,比如在返回True的過程中抄腔,如果隊列中的項目被取走探遵。
  • q.qsize():返回隊列中目前項目的正確數(shù)量,結(jié)果也不可靠妓柜,理由同q.empty()和q.full()一樣

線程Queue

同進程隊列一樣箱季,線程也有對于的方法,叫做線程Queue.

import queue

q=queue.Queue(3)   # 隊列:先進先出,指定隊列的大小

q.put(1)  # 向隊列中放入數(shù)據(jù)
q.put(2)
q.put(3)
print(q.get()) # 從隊列中取出數(shù)據(jù)
# q.put(4)    # 當隊列滿后會等待有空閑位置時再放入
# q.put_nowait(4)  # 立即放入數(shù)據(jù)棍掐,不等待藏雏,如果隊列已經(jīng)滿,則會報錯。

q.put(4,block=False) # 與put_nowait()方法一樣掘殴,設置不等待赚瘦,直接放入
q.put(4,block=True,timeout=3)   # 等待,且超時時間為3s


優(yōu)先級隊列:

import queue

q=queue.PriorityQueue(3)  # 優(yōu)先級隊列

q.put((10,'a')) # 指定優(yōu)先級奏寨,數(shù)字越小起意,優(yōu)先級越高
q.put((-3,'b'))
q.put((100,'c'))

print(q.get())
print(q.get())
print(q.get())

# 輸出結(jié)果:
(-3, 'b')
(10, 'a')
(100, 'c')

堆棧,后進先出:

import queue

q=queue.LifoQueue(3) # 堆棧:后進先出
q.put(1)
q.put(2)
q.put(3)

print(q.get())
print(q.get())
print(q.get())

輸出:

3
2
1

生產(chǎn)者和消費者模型

為了避免死鎖問題病瞳,能夠解耦合揽咕,定義了生產(chǎn)者消費者模型。生產(chǎn)者只需要創(chuàng)造數(shù)據(jù)套菜,然后將數(shù)據(jù)放入隊列亲善,消費者則從隊列中取出數(shù)據(jù),對數(shù)據(jù)進行消費逗柴。
下面是使用多進程實現(xiàn)了簡單的生產(chǎn)者和消費者模型:

from multiprocessing import Process,Queue
import random
import time

def producer(name,food,q):
    for i in range(10):
        res='%s%s' %(food,i)
        time.sleep(random.randint(1,3))
        q.put(res)
        print("廚師[%s]生產(chǎn)了<%s>" %(name,res))

def consumer(name,q):
    while True:
        res=q.get()
        time.sleep(random.randint(1,3))
        print('吃貨[%s]吃了<%s>' %(name,res))

if __name__=='__main__':
    q=Queue()
    p1=Process(target=producer,args=('andy','包子',q))
    c1=Process(target=consumer,args=('bob',q))

    p1.start()
    c1.start()
    print('主進程')

在實際的應用中蛹头,可能會有多個生產(chǎn)者和消費者,而且我們必須保證在生產(chǎn)者已經(jīng)生產(chǎn)完數(shù)據(jù)戏溺,并且消費者消費完數(shù)據(jù)后程序正常退出渣蜗,所以這里需要使用到JoinableQueue模塊。

from multiprocessing import Process,JoinableQueue   # 導入可以使用join方法的模塊
import random
import time

def producer(name,food,q):
    for i in range(3):
        res='%s%s' %(food,i)
        time.sleep(random.randint(1,3))
        q.put(res)
        print("廚師[%s]生產(chǎn)了<%s>" %(name,res))

def consumer(name,q):
    while True:
        res=q.get()
        time.sleep(random.randint(1,3))
        print('吃貨[%s]吃了<%s>' %(name,res))
        q.task_done()    # 通過使用隊列的task_done方法旷祸,通知每一次從隊列取出的信息

if __name__=='__main__':
    q=JoinableQueue()
    p1=Process(target=producer,args=('andy','包子',q))
    p2=Process(target=producer,args=('Tom','包子',q))

    c1=Process(target=consumer,args=('bob',q))
    c2=Process(target=consumer,args=('Lucy',q))
    c3=Process(target=consumer,args=('David',q))
    c1.daemon=True     # 設置為守護進程炫刷,當主進程運行完畢時眶诈,此子進程也退出
    c2.daemon=True
    c3.daemon=True

    p1.start()
    p2.start()
    c1.start()
    c2.start()
    c3.start()

    p1.join()     # 等待生產(chǎn)子進程運行結(jié)束
    p2.join()
    q.join()      # 等待隊列為空 后結(jié)束主進程
    print('主進程')



說明:

  • JoinableQueue([maxsize]):這就像是一個Queue對象帽蝶,但隊列允許項目的使用者通知生成者項目已經(jīng)被成功處理没龙。通知進程是使用共享的信號和條件變量來實現(xiàn)的五辽。
  • q.task_done():使用者使用此方法發(fā)出信號好乐,表示q.get()的返回項目已經(jīng)被處理瘾蛋。如果調(diào)用此方法的次數(shù)大于從隊列中刪除項目的數(shù)量搁拙,將引發(fā)ValueError異常
  • q.join():生產(chǎn)者調(diào)用此方法進行阻塞掺炭,直到隊列中所有的項目均被處理辫诅。阻塞將持續(xù)到隊列中的每個項目均調(diào)用q.task_done()方法為止
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市涧狮,隨后出現(xiàn)的幾起案子炕矮,更是在濱河造成了極大的恐慌,老刑警劉巖者冤,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肤视,死亡現(xiàn)場離奇詭異,居然都是意外死亡涉枫,警方通過查閱死者的電腦和手機邢滑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來愿汰,“玉大人困后,你說我怎么就攤上這事乐纸。” “怎么了摇予?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵汽绢,是天一觀的道長。 經(jīng)常有香客問我侧戴,道長宁昭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任救鲤,我火速辦了婚禮久窟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘本缠。我一直安慰自己斥扛,他們只是感情好,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布丹锹。 她就那樣靜靜地躺著稀颁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪楣黍。 梳的紋絲不亂的頭發(fā)上匾灶,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天,我揣著相機與錄音租漂,去河邊找鬼阶女。 笑死,一個胖子當著我的面吹牛哩治,可吹牛的內(nèi)容都是我干的秃踩。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼业筏,長吁一口氣:“原來是場噩夢啊……” “哼憔杨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蒜胖,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤消别,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后台谢,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體寻狂,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年朋沮,在試婚紗的時候發(fā)現(xiàn)自己被綠了蛇券。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖怀读,靈堂內(nèi)的尸體忽然破棺而出诉位,到底是詐尸還是另有隱情,我是刑警寧澤菜枷,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布苍糠,位于F島的核電站,受9級特大地震影響啤誊,放射性物質(zhì)發(fā)生泄漏岳瞭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一蚊锹、第九天 我趴在偏房一處隱蔽的房頂上張望瞳筏。 院中可真熱鬧,春花似錦牡昆、人聲如沸姚炕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽柱宦。三九已至,卻和暖如春播瞳,著一層夾襖步出監(jiān)牢的瞬間掸刊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工赢乓, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留忧侧,地道東北人。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓牌芋,卻偏偏與公主長得像蚓炬,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子姜贡,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 隊列 進程彼此之間互相隔離试吁,要實現(xiàn)進程間通信(IPC)棺棵,multiprocessing模塊支持兩種形式:隊列和管道...
    knot98閱讀 277評論 0 0
  • 進程間通信——隊列和管道(multiprocess.Queue烛恤、multiprocess.Pipe) 進程間通信 ...
    go以恒閱讀 1,782評論 0 3
  • 顧名思義母怜,進程即正在執(zhí)行的一個過程。進程是對正在運行程序的一個抽象缚柏。進程的概念起源于操作系統(tǒng)苹熏,是操作系統(tǒng)最核心的概...
    SlashBoyMr_wang閱讀 1,137評論 0 2
  • 什么是進程 進程(Process)是計算機中的程序關(guān)于某數(shù)據(jù)集合上的一次運行活動,是系統(tǒng)進行資源分配和調(diào)度的基本單...
    可笑的黑耀斑閱讀 1,004評論 0 0
  • @(python)[筆記] 目錄 一袱耽、什么是進程 1.1 進程的概念 進程的概念起源于操作系統(tǒng),是操作系統(tǒng)最核心的...
    CaiGuangyin閱讀 1,259評論 0 9