1. 程式人生 > >python多執行緒之Lock版生產者消費者模式

python多執行緒之Lock版生產者消費者模式

python多執行緒之lock版生產者消費者模式,謹以此文記之。

python多執行緒技術,仁者見仁智者見智,有道其雞肋,有道其乖張。暫且不去評論。本文僅述其淺淺的應用罷了。如下見祥例說明。

本文利用多執行緒技術,模擬在python爬蟲環境中的應用,分為生產者部分和消費者部分,也就是將一個爬蟲專案分為兩個部分,獲取將要爬的取詳細資訊的URL部分,和爬取該URL中的關鍵資訊的部分。生產者模擬第一部分,消費者模擬第二部分。也就是說,生產者負責生成指定的詳情頁面的URL,消費者負責使用該URL,獲取詳細資訊。

將整個場景模擬為賺錢和花錢。生產者賺錢,消費者花錢,當消費者發現金錢不夠花的時候,跳過,等有錢的時候再花錢。(消費者模擬再爬蟲專案未正式結束之前,生成URL的程式碼跟不上消費URL的程式碼的節奏時,跳過主要程式碼,等到生成了相關URL時,再繼續執行)

程式碼實現:

首先,匯入三個包,以下三個包,time用於延時,random生成隨機數,threading用於建立執行緒

import time
import random
import threading

定義全域性變數,在這裡定義了一個全域性鎖,主要是為了避免在多個執行緒處理全域性變數時,發生的紊亂問題。

gMoney = 1000 #設定初始金錢
gLock = threading.Lock()#建立全域性鎖
gTotletimes = 10 #定義生產者生產的總次數,模擬爬蟲需要爬取URL的總數
gTimes = 0 #定義已經爬取的URL數

然後,建立生產者:在生產者中,隨機生產money,將money新增到全域性gMoney中,供消費者消費,相當於爬蟲生產URL新增到全域性URL列表中一樣。

class Producter(threading.Thread):
    def run(self):
        global gMoney#宣告全域性變數
        global gTimes
        global gTotletimes
        while True:
            money = random.randint(100,1000)#生產隨機數量的money
            gLock.acquire()#開啟鎖
            if gTimes >= gTotletimes:#判斷是否完成生產任務,如果完成則跳出,釋放鎖
                gLock.release()
                break
            gTimes += 1
            gMoney += money#將生產的金錢新增到全域性變數中
            print("%s生產者生產了%d元錢,總共有%d元錢"%(threading.current_thread(),money,gMoney))
            gLock.release()#釋放鎖
            time.sleep(0.2)

建立消費者,隨機產生需要消費的金額,如果全域性變數中的金額足夠,則消費,否則等待再消費。

class Consumer(threading.Thread):
    def run(self):
        global gMoney
        global gTimes
        global gTotletimes
        while True:
            money = random.randint(100,1000)#生成需要消費的金額
            gLock.acquire()
            if money <= gMoney:#如果金錢足夠,則消費
                gMoney -= money
                print("{}消費者消費了{}元錢,還有{}元錢".format(threading.current_thread(),money,gMoney))
            else:
                if gTimes >= gTotletimes:#如果生產者不在生產,金錢也不夠消費,則退出
                    gLock.release()
                    break
                print("消費者%s準備消費%d元錢,不足"%(threading.current_thread(),money))
            gLock.release()
            time.sleep(0.2)

如下為主函式:

def main():
    for i in range(3):#生成3個消費者
        t2 = Consumer(name='消費者%d'%(i))
        t2.start()

    for x in range(3):#生成3個生產者
        t1 = Producter(name='生產者{}'.format(x))
        t1.start()

if __name__ == '__main__':
    main()

執行如下:

生產者生產了10次,消費著在整體程式未執行結束時,有一次不足,等待之後在次消費。

結束