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

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. BAT批处理中的字符串处理详解(字符串截取)

    BAT批处理中的字符串处理详解(字符串截取)   BAT批处理中的字符串处理详解(字符串截取 批处理有着具有非常强大的字符串处理能力,其功能绝不低于C语言里面的字符串函数集.批处理中可实现的字符串处理 ...

  2. 基于Python+Django重定向的例子

    Django源码, 这里HttpResponseRedirect和HttpResponsePermanentRedirect没有太大差别,前者是返回302临时重定向,后者返回301永久重定向 clas ...

  3. 【js】正则

    复习字符串操作search 查找substring 获取子字符串charAt 获取某个字符split 分割字符串,获得数组 <script> var str="abcdef&qu ...

  4. pycharm中split的应用

    #input 字符串 “5+9” value = "5+9" v1,v2 = value.split("+")#意思是把加号前后的5和9分别赋值给v1,v2 v ...

  5. 6101 最优贸易 (双向spfa)

    描述C国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双向通行的 ...

  6. Spring异步调用原理及SpringAop拦截器链原理

    一.Spring异步调用底层原理 开启异步调用只需一个注解@EnableAsync @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTI ...

  7. MyBatis(三)MyBatis的增删改查

    (1)接口中编写方法 public Emp getEmp(Integer id); public void addEmp(Emp emp); public void deleteEmp(Integer ...

  8. CCTV5 前端

    get :  fre = 11868  symbolrate  = 27500 pls_n=0------167    CCTV 9------------168    CCTV 3--------- ...

  9. 6.6 Pandora 实操 - API/SDK

    创建实时仓库 连接日志仓库 点击到工作流查看 通过 Java sdk 打数据 通过 java sdk 对应字段打数据,先打到实时仓库(消息队列),对应再会打到日志仓库(做存储). 代码见 Sequen ...

  10. Pandora 生成 Token

    生成 token 打数据到仓库 通过 api 签名工具实现 最后通过curl -XPOST -H "Content-Type: application/json" -H " ...