並行プログラミング - キュー、生産者 - 消費者モデル

1.キュー

プロセス間通信(IPC)を達成するために、それぞれ他のプロセスから単離され、マルチプロセッシングモジュールには2つの形式をサポート:キューとパイプラインは、これらの2つの方法は、使用するメッセージです。

1.1キュー(待ち行列)

そして、基礎となる実装フォームにパイプをロックします

1.2キュー方法

  • キュー([MAXSIZE])

    共有プロセスキューを作成します。

    MAXSIZE:キュー・エントリの最大許容数、省略した場合、サイズ制限なし。

    from multiprocessing import Queue
    q = Queue(5)      #队列最大项数5
  • q.put(OBJ、ブロック=真、[タイムアウト])

    from multiprocessing import Queue
    q = Queue(1)
    
    # 将obj放入队列,如果队列已满,将阻塞至有可用空间为止
    q.put('a')
    
    # block控制阻塞行为,block默认为True,如果设置为False且Queue已满,则引发Queue.Full异常
    q.put('b', block=False)
    q.put_nowait('e')     # 等同于q.put('b', block=False)
    
    # timeout控制阻塞时间,block为True,在计时结束后,如果Queue还是满的,则引发Queue.Full异常
    q.put('c', block=True, timeout=2)
    q.put('d', timeout=2)
  • q.get(ブロック=真、[タイムアウト])

      from multiprocessing import Queue
      q = Queue()
    
      # 从队列中弹出一个元素,如果队列已空,将阻塞至可以获取到元素为止
      q.get()
    
      # block控制阻塞行为,block默认为True,如果设置为False且Queue已空,则引发Queue.Empty异常
      q.get(block=False)
      q.get_nowait()      # 等同于q.get(block=False)
    
      # timeout控制阻塞时间,block为True,在计时结束后,如果Queue还是空的,则引发Queue.Empty异常
      q.get(block=True, timeout=2)
      q.get(timeout=2)

2.生産者 - 消費者モデル

2.1生産者 - 消費者モデルは何ですか

生産者 - 消費者モデルは、容器の生産者と消費者によって解決される強い結合の問題です。生産者と消費者が直接相互に通信していない、とキューを遮断することによって通信する、消費者を待たずに本番データの処理が完了した後にプロデューサーので、直接スローのブロッキングキューは、消費者がデータへのプロデューサーを見つけることができませんが、キューをブロックから直接採取し、キューが処理能力の生産者と消費者のバランスをとる、ブロッキングバッファーに相当します。

2.2なぜ生産者 - 消費者モデルを使用

スレッドの世界では、スレッドが本番データのプロデューサーである、消費者は、スレッド消費データです。迅速に処理プロデューサー、そして消費者の処理速度が非常に遅い場合、マルチスレッドの開発では、プロデューサは、生産データを継続するために、処理された消費者を待たなければなりません。消費者の能力がプロデューサーよりも大きい場合には、同じトークンによって、消費者は生産者を待たなければならないでしょう。その生産者と消費者のパターンの導入をこの問題を解決するには。

2.3生産消費者のロールモデル

並行プログラミングで生産者と消費者の使用パターンは、並行性の問題の大半を解決することができます。生産と消費のスレッドスレッドのバランスをとる能力を加工してデータ処理プログラムの速度を上げるために、全体的なパターン。

# 生产者消费者模型总结

# 程序中有两类角色
一类负责生产数据(生产者)
一类负责处理数据(消费者)

# 引入生产者消费者模型为了解决的问题是:
平衡生产者与消费者之间的工作能力,从而提高程序整体处理数据的速度

# 如何实现:
生产者<-->队列<——>消费者
# 生产者消费者模型实现类程序的解耦和

生産者 - 消費者モデルを使用して2.4キューの実装

import time, random
from multiprocessing import Process, Queue


def producer(q):
    """生产者"""
    for i in range(10):
        time.sleep(random.randint(1, 3))
        q.put(i)
        print(f'生产{i}')


def consumer(q):
    """消费者"""
    while True:
        time.sleep(random.randint(0, 5))
        res = q.get()
        print(f'消费{res}')


if __name__ == '__main__':
    q = Queue()
    p = Process(target=producer, args=(q,))
    p.start()
    c = Process(target=consumer, args=(q,))
    c.start()

空のQをとった後のp、それが終了した後、生産の生産が、消費者Cは、(死のサイクルに残ったとq.getに従事していますので、この時点では、主な問題は、プロセスが終了したことがないということです)このステップ。

解決策が、生産はキューの最後に、完了し、消費者は死のサイクルから抜け出すことができ、信号を受信した後に終了して、その後、信号を送信した後、それが生産することができます。

解決策1:なし生産者が最後にキューにタグを追加するには、消費者はwhileループから抜け出すだろうNoneに取得します

import time, random
from multiprocessing import Process, Queue


def producer(q, name):
    """生产者"""
    for i in range(10):
        time.sleep(random.randint(1, 3))
        res = f'{name}生产{i}'
        q.put(res)
        print(res)
    q.put(None)


def consumer(q, name):
    """消费者"""
    while True:
        time.sleep(random.randint(0, 5))
        if not res:
            break
        res = q.get()
        print(f'{name}消费{res}')


if __name__ == '__main__':
    q = Queue()
    p1 = Process(target=producer, args=(q, 'p1'))
    p2 = Process(target=producer, args=(q, 'p2'))
    p1.start()
    p2.start()
    c = Process(target=consumer, args=(q, 'c'))
    c.start()

質問:複数のコンシューマ時には、あなたがNoneに消費者のアクセス権を持っている場合、消費者は以上ですが、キュー内の要素は、要件を満たしていない、そこにある、キュー複数のドーピングなしの終わりではありません。

対処方法2:プロデューサー後にタグになしキューを追加するには、メインプロセス

import time, random
from multiprocessing import Process, Queue


def producer(q, name):
    """生产者"""
    for i in range(10):
        time.sleep(random.randint(1, 3))
        res = f'{name}生产{i}'
        q.put(res)
        print(res)


def consumer(q, name):
    """消费者"""
    while True:
        time.sleep(random.randint(0, 5))
        res = q.get()
        if not res:
            break
        print(f'{name}消费{res}')


if __name__ == '__main__':
    q = Queue()
    p1 = Process(target=producer, args=(q, 'p1'))
    p2 = Process(target=producer, args=(q, 'p2'))
    p1.start()
    p2.start()
    c = Process(target=consumer, args=(q, 'c'))
    c.start()
    p1.join()
    p2.join()
    q.put(None)

質問:どのように多くの生産者が、どのように多くのNoneを追加していないする必要がどのように多くの消費者が何回参加する必要があり

3. JoinableQueue生産者 - 消費者モデルを実現

3.1 JoinabaleQueue

  • JoinabaleQueue([MAXSIZE])

    省略された場合、キューに入れることができるエントリの最大数をMAXSIZEなし、サイズの制限。

3.2 JoinabaleQueue方法

  • q.task_done()

    それぞれが取得した後の数が呼び出しの数キューから項目を削除するには、このメソッドよりも大きい場合、信号は、取得使命は、終了した、とValueErrorの例外がスローされます

  • q.join()

    ブロックは、キュー内のすべてのタスクの完了を待っています

3.3 JoinabaleQueue使い方

from multiprocessing import JoinableQueue

q = JoinableQueue()

q.put('a')      # 往队列里放入了一个任务
q.put('b')

q.get()
q.task_done()       # 完成了一个任务
q.get()
# q.join            # 如果放在这里,任务数并没有降为0,将会一直阻塞
q.task_done()
q.join()        # 阻塞,等待所有任务完成

3.4 JoinableQueueは、生産者 - 消費者モデルを実現

import time, random
from multiprocessing import Process, JoinableQueue


def producer(q, name):
    """生产者"""
    for i in range(10):
        time.sleep(random.randint(0, 2))
        res = f'{name}生产{i}'
        q.put(res)
        print(res)


def consumer(q, name):
    """消费者"""
    while True:
        time.sleep(random.randint(0, 2))
        res = q.get()
        q.task_done()       # 一个任务已完成,任务数减一
        print(f'{name}消费{res}')


if __name__ == '__main__':
    q = JoinableQueue()
    p1 = Process(target=producer, args=(q, 'p1'))
    p2 = Process(target=producer, args=(q, 'p2'))
    p1.start()
    p2.start()
    c = Process(target=consumer, args=(q, 'c'))
    c.daemon = True     # 将消费者设置为守护进程
    c.start()
    p1.join()       # 确保所有的生产者任务都执行,即任务都加入了队列
    p2.join()
    q,join()        # 如果队列里所有任务都被执行,则阻塞解除,主进程结束,守护进程结束

おすすめ

転載: www.cnblogs.com/zj420255586/p/11529645.html