• condition版生产者与消费者模式


    1.简介

    在爬虫中,生产者与消费者模式是经常用到的。我能想到的比较好的办法是使用redis或者mongodb数据库构造生产者消费者模型。如果直接起线程进行构造生产者消费者模型,线程容易假死,也难以构造复杂的生产者消费者模型。这里提供的condition版其实是最基本的生产者消费者模型的改良版,为了保护数据安全依旧是要开锁进行操作,但是不会循环的一直开锁,而是一旦条件不符合,则会阻塞,直到符合运行程序的条件。但是还是太low,不过这种思路值得借鉴。

    2.代码

    #  -*-coding:utf8 -*-
    
    import threading
    
    # Lock版本的生产者消费者模式可以正常的运行,但是太消耗CPU资源。
    # 使用while循环的方式一直开锁解锁,很消耗资源。threading.Condition可以看作Lock的改良版
    # 还有一个更好的模式就是用threading.Condition来实现
    # threading.Condition可以在没有数据的时候处于阻塞等待状态,一旦有合适的数据了,
    # 还可以使用notify相关的函数来通知其他处于等待状态的线程。这样就可以不用做一些无用的上锁
    # 和解锁的操作,可以提高程序的性能。
    
    # 1.acquire:获取锁
    # 2.release:解锁
    # 3.wait:释放内部占用的锁,同时线程被挂起。可以被其他线程用notify和notify_all函数唤醒,
    # 被唤醒后会继续等待获取锁,获取锁后继续执行下面的代码
    # 4.notify:唤醒一个挂起的线程,默认是第一个等待的线程。注意:notify不会释放所占用的锁
    # 5.notify_all:通知所有正在等待的线程。notify和notify_all不会释放锁。并且需要在release之前调用
    
    #  -*-coding:utf8 -*-
    import threading
    import random
    import time
    
    gMoney = 1000
    gCondition = threading.Condition()
    gTimes = 0
    gTotalTimes = 30
    
    
    class Producer(threading.Thread):
        def run(self):
            global gMoney
            global gTimes
            while True:
                money = random.randint(100, 1000)
                gCondition.acquire()
                if gTimes >= gTotalTimes:
                    gCondition.release()
                    break
                gMoney += money
                gTimes += 1
                print('%s生产了%s元钱,剩余%s元钱' % (threading.current_thread(), money, gMoney))
                gCondition.notify_all()
                gCondition.release()
                time.sleep(0.5)
    
    
    class Consumer(threading.Thread):
        def run(self):
            global gMoney
            while True:
                money = random.randint(100, 1000)
                gCondition.acquire()
                while gMoney < money:
                    if gTimes >= gTotalTimes:
                        gCondition.release()
                        return
                    # 当不满足条件时,直接进入阻塞,不在循环开锁,关锁的消耗资源的操作
                    gCondition.wait()
                gMoney -= money
                print('%s消费了%d元钱,剩余%d元钱' % (threading.current_thread(), money, gMoney))
                gCondition.release()
                time.sleep(0.5)
    
    
    def main():
        for x in range(5):
            t = Consumer(name='消费者线程%s' % x)
            t.start()
        for x in range(2):
            t = Producer(name='生产者线程%s' % x)
            t.start()
    
    
    if __name__ == '__main__':
        main()
    View Code
  • 相关阅读:
    react 调用webIm
    css样式问题解决
    学习animejs
    vue,在模块中动态添加dom节点,并监听
    vue 关于solt得用法
    vue-cli 安装过程出现错误
    处理参数中存在多个连续空格,只显示一个空格,复制后搜索不到得问题
    http StatusCode(状态码)
    修改表单小技巧
    关于swiper中包含表单元素的bug
  • 原文地址:https://www.cnblogs.com/xufengnian/p/10788204.html
Copyright © 2020-2023  润新知