在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。

1.什么是生产者消费者模型

生产者:比喻的是程序中负责产生数据的任务

消费者:比喻的是程序中负责处理数据的任务

生产者 --》共享的介质(队列)《-- 消费者

2.为何用

实现了生产者与消费者的解耦和,生产者可以不停地生产,消费者也可以不停地消费

从而平衡了生产者的生产能力与消费者的消费能力,提升了程序整体运行的效率

3、什么时候用?

当我们的进程中存在明显的两类任务,一类负责产生数据,另外一类负责处理数据

当时就应该考虑使用生产者消费者模型来提升程序的效率。

下面我们实现这样一个过程

  • 维护一个整数列表 integer_list ,共有两个线程
  • Producer 类对应一个线程,功能:随机产生一个整数,加入整数列表之中
  • Consumer 类对应一个线程,功能:从整数列表中 pop 掉一个整数
  • 通过 time.sleep 来表示两个线程运行速度,设置成 Producer 产生的速度没有 Consumer 消耗的快

如果可以在第一次查询到列表为空的时候就开始等待,直到列表不为空(收到通知而不是一遍一遍地查询),资源开销就可以节省很多。 Condition 对象就可以解决这个问题,它与一般锁的区别在于,除了可以 acquire release ,还多了两个方法 wait notify

import time
import threading
import random


class Producer(threading.Thread):
    def __init__(self, condition, integer_list):
        threading.Thread.__init__(self)
        self.condition = condition
        self.integer_list = integer_list
    def run(self):
        while True:
            random_integer = random.randint(0, 100)
            with self.condition:
                self.integer_list.append(random_integer)
                print('integer list add integer {}'.format(random_integer))
                self.condition.notify()
            time.sleep(1.2 * random.random())



class Consumer(threading.Thread):
    def __init__(self, condition, integer_list):
        threading.Thread.__init__(self)
        self.condition = condition
        self.integer_list = integer_list
    def run(self):
        while True:
            with self.condition:
                if self.integer_list:
                    integer = self.integer_list.pop()
                    print('integer list lose integer {}'.format(integer))
                    time.sleep(random.random())
                else:
                    print('there is no integer in the list')
                    self.condition.wait()
def main():
    integer_list = []
    condition = threading.Condition()
    th1 = Producer(condition, integer_list)
    th2 = Consumer(condition, integer_list)
    th1.start()
    th2.start()
if __name__ == '__main__':
    main()

运行结果:

integer list add integer 54
integer list lose integer 54
there is no integer in the list
integer list add integer 61
integer list lose integer 61
there is no integer in the list
integer list add integer 86
integer list lose integer 86
there is no integer in the list
integer list add integer 11
integer list lose integer 11
integer list add integer 16
integer list lose integer 16
there is no integer in the list
integer list add integer 52
integer list lose integer 52
there is no integer in the list
integer list add integer 18
integer list lose integer 18
there is no integer in the list
integer list add integer 84
integer list lose integer 84
integer list add integer 79
integer list lose integer 79
there is no integer in the list
integer list add integer 20


Process finished with exit code -1

在生产出整数时 notify 通知 wait 的线程可以继续了
消费者查询到列表为空时调用 wait 等待通知( notify )