Pythonの生産/消費者モデルの実装プロセスの解析

1.マルチスレッド

インポート通し
インポートキュー
インポートロギング
logging.basicConfig(レベル= logging.INFO、フォーマット=「%(いるasctime)S - %(levelname)。■ - >%(FUNCNAME)が行%(LINENOのS)D:\ N%(メッセージ)をS')
ログ= logging.getLogger()

DEFプロデューサ(Q):
範囲のkに対する(10):
q.put(K)
logging.info( "プット%S項目キューに" %のK)
ブロック全てプロデューサーの主な消費者がそのプットすべてのキューメンバーを取得するまで
q.join()


defの消費者(Q):
真の中:
「」」
、キューが空とq.getれている場合(ブロック=真)
ソースコード内のデフォルトのブロックがTrueであるので、
キューは、キューが新しいアイテムを置くutilの永遠ボックます。
「」"
項目= q.get()
logging.info(%項目"キューの%sのメンバーから出て行け")

は(q.join通知)消費者がキューのメンバーから出ている
)q.task_done(

__name__ ==「__main__場合「:
thread_num = 5
キューの#限界最大長さ
Q = queue.Queue(MAXSIZE = 5)
生産= [threading.Thread(目標=プロデューサー、引数=(Q、))]
消費者= [threading.Thread(目標=コンシューマIの範囲内(thread_num)]のために、引数=(Q))
スタートプロデューサおよびコンシューマ
の生産におけるPRの:
pr.start()
CNのための消費者に:
cn.start()
プロデューサの#ブロックメインスレッド
pについてでプロデューサー:
p.join()
消費者の主#のブロック
Cでの消費者のために:
c.join()

の結果:コンソールがブロックされている見ることができます。消費者は、キューがソースコードq.get()パラメータブロックをTrueに構築されているので、あなたがブロックしたときに、リーチはブロックされている時間が、この手段であることを、すべてのメンバーの後の空、空のキューになっ仕上げキューを費やすので、トゥルーエンドフラグは、消費者が死のサイクルを終了するように設定しなければならないときに、私たちは
、この方法についての改善:

 

 

プロデューサーフラグなしのtell消費者の生産いずれも、最終消費者を取得していないとき、死のサイクルから抜け出すの最後に追加すると、これは消費の問題を解決するだろう、それがブロックされています:

メインスレッドが参加する前に、各スレッドは死のサイクルから抜け出すように、スレッドなしプロデューサーの同じ数を追加します。

import threading
import queue
import logging
logging.basicConfig(level = logging.INFO,format = '%(asctime)s  - %(levelname)s -->%(funcName)s  at line %(lineno)d: \n %(message)s')
log= logging.getLogger()

def  producer(q):
    for k in range(10):
        q.put(k)
        logging.info("put %s item into queue "%k)
    # block all producer main until consumer get all queue members that put
    q.join()


def consumer(q):
    while True:
        """
            if queue been empty and q.get(block=True),
        because default block in source code is True ,
        queue will bock forever util queue put new item .
        """
        item=q.get()
        logging.info("get out of %s member of queue " % item)
        if item == None:
            logging.info("get None stop consumer from while loop")
            break
        # notify q.join() consumer has get out of member of queue
        q.task_done()

if __name__ == '__main__':
    thread_num=5
    # limit max length of queue
    q = queue.Queue(maxsize=5)
    producers=[threading.Thread(target=producer,args=(q,))]
    consumers=[threading.Thread(target=consumer,args=(q,))  for i in range(thread_num)]
    # start producer and  consumer
    for pr in producers:
        pr.start()
    for cn in consumers:
        cn.start()
    # block main thread of producer
    for p  in producers:
        p.join()
    # put same number of thread_num None to break thread from consumer while
    for i in range(thread_num):
        q.put(None)
    # block main of consumer
    for c in consumers:
        c.join()

  

2019-12-21 20:37:00,206 - INFO -->consumer at line 23:
get out of None member of queue
2019-12-21 20:37:00,206 - INFO -->consumer at line 25:
get None mean break
2019-12-21 20:37:00,206 - INFO -->consumer at line 25:
get None mean break
2019-12-21 20:37:00,206 - INFO -->consumer at line 25:
get None mean break
2019-12-21 20:37:00,206 - INFO -->consumer at line 25:
get None mean break
2019-12-21 20:37:00,206 - INFO -->consumer at line 23:
get out of None member of queue
2019-12-21 20:37:00,207 - INFO -->consumer at line 25:
get None mean break

Process finished with exit code 0

结果:正常释放所有线程,但是好像每次线程都要加个标志太麻烦,感觉,能不能有更好的办法呢,当然接着往下看:

改良consumer方法在每次消费队列之前检查队列queue.empty() 是否为True,是就直接break跳出while loop:就不需要每次都加None标志了

import threading
import queue
import logging
logging.basicConfig(level = logging.INFO,format = '%(asctime)s  - %(levelname)s -->%(funcName)s  at line %(lineno)d: \n %(message)s')
log= logging.getLogger()

def  producer(q):
    for k in range(10):
        q.put(k)
        logging.info("put %s item into queue "%k)
    # block all producer main until consumer get all queue members that put
    q.join()


def consumer(q):
    while True:
        """
            if queue been empty and q.get(block=True),
        because default block in source code is True ,
        queue will bock forever util queue put new item .
        """
        if q.empty():break
        item=q.get()
        logging.info("get out of %s member of queue " % item)
        # notify q.join() consumer has get out of member of queue
        q.task_done()

if __name__ == '__main__':
    thread_num=5
    # limit max length of queue
    q = queue.Queue(maxsize=5)
    producers=[threading.Thread(target=producer,args=(q,))]
    consumers=[threading.Thread(target=consumer,args=(q,))  for i in range(thread_num)]
    # start producer and  consumer
    for pr in producers:
        pr.start()
    for cn in consumers:
        cn.start()
    # block main thread of producer
    for p  in producers:
        p.join()

  

j结果如下:

おすすめ

転載: www.cnblogs.com/SunshineKimi/p/12078175.html