1.简介

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

2.代码

  1. # -*-coding:utf8 -*-
  2.  
  3. import threading
  4.  
  5. # Lock版本的生产者消费者模式可以正常的运行,但是太消耗CPU资源。
  6. # 使用while循环的方式一直开锁解锁,很消耗资源。threading.Condition可以看作Lock的改良版
  7. # 还有一个更好的模式就是用threading.Condition来实现
  8. # threading.Condition可以在没有数据的时候处于阻塞等待状态,一旦有合适的数据了,
  9. # 还可以使用notify相关的函数来通知其他处于等待状态的线程。这样就可以不用做一些无用的上锁
  10. # 和解锁的操作,可以提高程序的性能。
  11.  
  12. # 1.acquire:获取锁
  13. # 2.release:解锁
  14. # 3.wait:释放内部占用的锁,同时线程被挂起。可以被其他线程用notify和notify_all函数唤醒,
  15. # 被唤醒后会继续等待获取锁,获取锁后继续执行下面的代码
  16. # 4.notify:唤醒一个挂起的线程,默认是第一个等待的线程。注意:notify不会释放所占用的锁
  17. # 5.notify_all:通知所有正在等待的线程。notify和notify_all不会释放锁。并且需要在release之前调用
  18.  
  19. # -*-coding:utf8 -*-
  20. import threading
  21. import random
  22. import time
  23.  
  24. gMoney = 1000
  25. gCondition = threading.Condition()
  26. gTimes = 0
  27. gTotalTimes = 30
  28.  
  29. class Producer(threading.Thread):
  30. def run(self):
  31. global gMoney
  32. global gTimes
  33. while True:
  34. money = random.randint(100, 1000)
  35. gCondition.acquire()
  36. if gTimes >= gTotalTimes:
  37. gCondition.release()
  38. break
  39. gMoney += money
  40. gTimes += 1
  41. print('%s生产了%s元钱,剩余%s元钱' % (threading.current_thread(), money, gMoney))
  42. gCondition.notify_all()
  43. gCondition.release()
  44. time.sleep(0.5)
  45.  
  46. class Consumer(threading.Thread):
  47. def run(self):
  48. global gMoney
  49. while True:
  50. money = random.randint(100, 1000)
  51. gCondition.acquire()
  52. while gMoney < money:
  53. if gTimes >= gTotalTimes:
  54. gCondition.release()
  55. return
  56. # 当不满足条件时,直接进入阻塞,不在循环开锁,关锁的消耗资源的操作
  57. gCondition.wait()
  58. gMoney -= money
  59. print('%s消费了%d元钱,剩余%d元钱' % (threading.current_thread(), money, gMoney))
  60. gCondition.release()
  61. time.sleep(0.5)
  62.  
  63. def main():
  64. for x in range(5):
  65. t = Consumer(name='消费者线程%s' % x)
  66. t.start()
  67. for x in range(2):
  68. t = Producer(name='生产者线程%s' % x)
  69. t.start()
  70.  
  71. if __name__ == '__main__':
  72. main()

condition版生产者与消费者模式的更多相关文章

  1. 用ReentrantLock和Condition实现生产者和消费者模式

    前面一篇文章<wait.notify应用场景(生产者-消费者模式)>是一种生产者消费者模式实现,今晚这是Lock方式实现,下面是源码: 生产者代码: /** * 生产者 * * @auth ...

  2. 【爬虫】Condition版的生产者和消费者模式

    Condition版的生产者和消费者模式 threading.Condition 在没有数据的时候处于阻塞状态,有数据可以使用notify的函数通知等等待状态的线程运作 threading.Condi ...

  3. 【爬虫】Load版的生产者和消费者模式

    ''' Lock版的生产者和消费者模式 ''' import threading import random import time gMoney = 1000 # 原始金额 gLoad = thre ...

  4. Java并发编程(4)--生产者与消费者模式介绍

    一.前言 这种模式在生活是最常见的,那么它的场景是什么样的呢? 下面是我假象的,假设有一个仓库,仓库有一个生产者和一个消费者,消费者过来消费的时候会检测仓库中是否有库存,如果没有了则等待生产,如果有就 ...

  5. 使用libuv实现生产者和消费者模式

    生产者和消费者模式(Consumer + Producer model) 用于把耗时操作(生产线程),分配给一个或者多个额外线程执行(消费线程),从而提高生产线程的响应速度(并发能力) 定义 type ...

  6. java生产者与消费者模式

    前言: 生产者和消费者模式是我们在学习多线程中很经典的一个模式,它主要分为生产者和消费者,分别是两个线程, 目录 一:生产者和消费者模式简介 二:生产者和消费者模式的实现 声明:本例来源于java经典 ...

  7. Java多线程设计模式(2)生产者与消费者模式

    1 Producer-Consumer Pattern Producer-Consumer Pattern主要就是在生产者与消费者之间建立一个“桥梁参与者”,用来解决生产者线程与消费者线程之间速度的不 ...

  8. java 线程并发(生产者、消费者模式)

    线程并发协作(生产者/消费者模式) 多线程环境下,我们经常需要多个线程的并发和协作.这个时候,就需要了解一个重要的多线程并发协作模型“生产者/消费者模式”. Ø 什么是生产者? 生产者指的是负责生产数 ...

  9. java进阶(40)--wait与notify(生产者与消费者模式)

    文档目录: 一.概念 二.wait的作用 三.notify的作用 四.生产者消费者模式 五.举例 ---------------------------------------分割线:正文------ ...

随机推荐

  1. MQTT服务器的搭建(Windows平台)

    人工智能.智能家居越来越火,在服务器和多个终端进行通信的过程中使用传统的请求/回答(Request/Response)模式已经过时,伴随而来的是发布/订阅(Publish/Subscribe)模式-- ...

  2. SQL Server 中执行Shell脚本计算本地文件的内容大小

    SQL Server 数据库中除了能执行基本的SQL语句外,也可以执行Shell脚本.默认安装后,SQL中的Shell脚本的功能是关闭的,需要手动打开, 执行以下脚本即可打开该功能. -- 允许配置高 ...

  3. java日志规约及配置示例终极总结

    目录 什么是日志 常用日志框架 日志级别详解 日志的记录时机 日志使用规约 logback 配置示例 loh4j2 配置示例 什么是日志? 简单的说,日志就是记录程序的运行轨迹,方便查找关键信息,也方 ...

  4. 【Codeforces】【网络流】【线段树】【扫描线】Oleg and chess (CodeForces - 793G)

    题意: 给定一个n*n的矩阵,一个格子上可以放一个车.其中有q个子矩阵,且q个子矩阵互不相交或者是重叠(但边界可以衔接).这q个子矩阵所覆盖的地方都是不能够放车的.车可以越过子矩阵覆盖的地方进行攻击( ...

  5. (转)InFluxDB数据库使用手册

    InfluxDB是一个开源的时序数据库,使用GO语言开发,特别适合用于处理和分析资源监控数据这种时序相关数据.而InfluxDB自带的各种特殊函数如求标准差,随机取样数据,统计数据变化比等,使数据统计 ...

  6. 【C语言程序】输出前50个素数

    #include <stdio.h> #include <stdlib.h> int main(void) {  ;  ;  ){   ;   ;i<x;i++){    ...

  7. VS2008中 VB 报错 检索 COM 类工厂中 CLSID 为 {28E68F9A-8D75-11D1-8DC3-3C302A000000} 的组件失败,原因是出现以下错误: 80040154 没有注册类 (异常来自 HRESULT:0x80040154 (REGDB_E_CLASSNOTREG))。

    Resvr32 .net中引用控件的名称 如果注册成功,问题不在出现 但是如果是在x64位的系统中,即使控件注册成功,错误依照提示,是因为大多数第三方写的COM控件,只支持32位的系统, 在VS中找到 ...

  8. vue_mint-ui

    npm install mint-ui -S main.js import { Button } from 'mint-ui'; import "mint-ui/lib/style.css& ...

  9. Wireshark简单使用教程3——附视频

    视频https://www.bilibili.com/video/av35763613?from=search&seid=10176480091153063668 目录 抓取干净流量包的用处所 ...

  10. Windows系统IntelliJ IDEA安装配置

    IntelliJ IDEA安装 IntelliJ IDEA,是java编程语言开发的集成环境,业界公认的最好的Java开发IDE之一.打开IDEA官方网站https://www.jetbrains.c ...