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()

执行结果

 

posted @ 2021-04-26 20:29  马铃薯1  阅读(76)  评论(0编辑  收藏  举报