14-多线程爬虫-Conditon版的生产者和消费者模式
Conditon版的生产者和消费者模式:
Lock版的生产者和消费者模式可以正常的运行。但是存在一个不足,在消费者中,总是通过while True死循环并且上锁的方式去判断gMoney钱够不够。
上锁是一个很耗费CPU资源的行为,因此这种方式不是最好的。还有一种更好的方式便是使用threading.Condition来实现
threading.Condition可以在没有数据的时候处于阻塞等待状态,一旦有合适的数据,还可以使用notify相关的函数来通知其他处于等待状态的线程。这样就可以不用做一些无用的上锁和解锁的操作,提高程序的性能。
注意:
threading.Condition类似threading.Lock,可以在修改全局数据的时候进行上锁,也可以在修改完毕后进行解锁。
# Conditon版的生产者和消费者模式 import threading import random import time gMoney = 0 gCondition = threading.Condition() gTimes = 0 class Producer(threading.Thread): def run(self) -> None: # 当前线程的对象 the_thread = threading.current_thread() global gMoney,gTimes while True: gCondition.acquire() if gTimes >= 10: gCondition.release() break money = random.randint(0,100) gMoney += money gTimes += 1 print("当前线程:{0}\t赚了{1}元,存款为{2}元".format(the_thread.name,money,gMoney)) # 当gMoney生产者完成依次挣钱时,通知所有正在等待的进程 gCondition.notify_all() gCondition.release() # time.sleep()延迟进程 time.sleep(1) class Consumer(threading.Thread): def run(self) -> None: # 当前线程的对象 the_thread = threading.current_thread() global gMoney while True: gCondition.acquire() money = random.randint(0,100) # 当gMoney小于money时,让线程处于wait等待状态 while gMoney < money: print("当前线程:{0}\t余额不足,预支付{1}元,但余额只有{2}元".format(the_thread.name,money,gMoney)) # 如果gTimes达到十次,代表生产者线程不再生产钱,gMoney也不会再增加,退出整个循环(程序)释放进程 if gTimes >=10: gCondition.release() return gCondition.wait() gMoney -= money print("当前线程:{0}\t花了{1}元,存款为{2}元".format(the_thread.name,money,gMoney)) gCondition.release() # time.sleep()延迟进程 time.sleep(1) def main(): # 创建五个生产者进程 for x in range(5): thread_producer = Producer(name="生产者{}".format(x)) thread_producer.start() # 创建五个消费者进程 for y in range(5): thread_consumer = Consumer(name="消费者{}".format(y)) thread_consumer.start() if __name__ == "__main__": main()
执行结果