多线程实现生产者消费者
1. Python多线程介绍
Python提供了两个有关多线程的标准库,thread和threading。thread提供了低级别的,原始的线程和一个锁。threading则是一个高级模块,提供了对thread的封装。一般情况下,使用threading是比较好的做法。
使用threading实现线程,只需要从threading.Thread类继承,并重写其中的__init__()方法和run()方法。
from threading import Thread class MyThread(Thread): def __init__(self): Thread.__init__(self) def run(self): print(self.thread_id, "start")
threading提供了一个锁:lock = threading.Lock(),调用锁的acquire()和release()方法可以使线程获得和释放锁。
需要注意的是,Python有一个GIL(Global Interpreter Lock)机制,任何线程在运行之前必须获取这个全局锁才能执行,每当执行完100条字节码,全局锁才会释放,切换到其他线程执行。
所以Python中的多线程不能利用多核计算机的优势,无论有多少个核,同一时间只有一个线程能得到全局锁,只有一个线程能够运行。
那么Python中的多线程有什么作用呢?为什么不直接使用Python中的多进程标准库?这里要根据程序执行的是IO密集型任务和计算密集型任务来选择。
当执行IO密集型任务时,比如Python爬虫,大部分时间都用在了等待返回的socket数据上,CPU此时是完全闲置的,这种情况下采用多线程较好。
当执行计算密集型任务时,比如图像处理,大部分时间CPU都在计算,这种情况下使用多进程才能真正的加速,使用多线程不仅得不到并行加速的效果,反而因为频繁切换上下文拖慢了速度。
2. threading实现生产者消费者
from threading import Thread
import timequeue = []
class Producer(Thread):def __init__(self,name):Thread.__init__(self) #调用未绑定的超类构造方法【必须显式调用父类的构造方法,否则不会执行父类构造方法,这个跟Java不一样】self.name = namedef run(self):while True:queue.append(1)print("Producer: %s create a product" % self.name)print("Producer: %s put a product into queue" % self.name)time.sleep(0)if len(queue) > 20:print ("queue is full!")time.sleep(1)
class Consumer(Thread):def __init__(self,name):Thread.__init__(self)self.name = namedef run(self):while True:try:queue.pop()print("Consumer: %s get a product" % self.name)time.sleep(2)except:print("Queue is empty!")time.sleep(2)print("Consumer: %s sleep 2 seconds" % self.name)if __name__ == '__main__':p1 = Producer("Producer-1")c1 = Consumer("Consumer-1")c2 = Consumer("consumer-2")p1.start()c1.start()c2.start()
输出如下:
Producer: Producer-1 create a product
Producer: Producer-1 put a product into queue
queue is full!
Producer: Producer-1 create a product
Producer: Producer-1 put a product into queue
queue is full!
分析:输出显示满了之后仍然显示了生产者在创建产品,表明线程run()方法中的运行次序被打乱了。这是因为没有加锁,导致消费者线程运行到一半的时候,生产者线程获得了CPU。
queue线程安全容器
ueue
这一线程安全的容器,可以方便的和多线程结合起来。 Queue
包括:
queue_tmp = Queue.Queue(10)class Producer(Thread):def __init__(self,name):Thread.__init__(self) #调用未绑定的超类构造方法【必须显式调用父类的构造方法,否则不会执行父类构造方法,这个跟Java不一样】self.name = namedef run(self):while True:queue_tmp.put(0)print("Producer: %s create a product" % self.name)print("Producer: %s put a product into queue\r\n" % self.name)class Consumer(Thread):def __init__(self,name):Thread.__init__(self)self.name = namedef run(self):while True:queue_tmp.get()print("Consumer: %s get a product" % self.name)
3. join()函数用法测试
join()函数的原型是join(timeout=None),它的作用是阻塞进程一直到线程退出或者到timeout的时间结束。
参考文章:https://www.jianshu.com/p/f09a112a71f7
转载于:https://www.cnblogs.com/honey-badger/p/8454873.html
多线程实现生产者消费者相关推荐
- Linux下实现多线程的生产者消费者问题
Linux下实现多线程的生产者消费者问题 一.原理的理解 生产者-消费者问题是一个经典的线程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制.在同一个线程地址空间内执行的两个线程 ...
- python多线程实现生产者消费者_用Python实现多线程“生产者-消费者”模型的简单例子...
用 Python 实现多线程"生产者 - 消费者"模型的简单例子 生产者消费者问题是一个著名的线程同步问题, 该问题描述如下: 有一个生产者在生产产品, 这些产品将提供给若干个消费 ...
- C++11 并发指南九(综合运用: C++11 多线程下生产者消费者模型详解)
前面八章介绍了 C++11 并发编程的基础(抱歉哈,第五章-第八章还在草稿中),本文将综合运用 C++11 中的新的基础设施(主要是多线程.锁.条件变量)来阐述一个经典问题--生产者消费者模型,并给出 ...
- java多线程之生产者消费者问题
今天研究了一下Java多线程,根据老师上课讲的和写的,自己写了一下多线程中的经典问题-----生产者消费者经典问题, package producerconsumer; public class Pr ...
- 多线程之生产者消费者模型
生产者消费者模型 1.为什么要使用生产者和消费者模式 2.案例 1.为什么要使用生产者和消费者模式 在线程开发中,生产者就是生产线程的线程,消费者就是消费线程的线程.在多线程开发中,如果生产者如理数据 ...
- 爬虫--05:多线程与生产者消费者模型
Crawler - 05: Multithreading- und Produzenten-Verbrauchermodell 多线程 一.多线程的基本介绍 1.介绍 2.程序中模拟多任务 二.创建多 ...
- Linux多线程实现生产者消费者进程(Linux+window代码)
原文链接:我的个人链接 Linux 常用多线程函数 pthread_create():创建一个线程 pthread_exit():退出一个线程 pthread_jion():阻塞当前线程,直到另一个线 ...
- 多线程设计模式:生产者-消费者
一.两个线程一个生产者一个消费者 需求情景 – 两个线程,一个负责生产,一个负责消费,生产者生产一个,消费者消费一个. 涉及问题 同步问题:如何保证同一资源被多个线程并发访问时的完整性.常用的同步方法 ...
- Python多线程实现生产者消费者模式
什么是生产者消费者模式 在软件开发的过程中,经常碰到这样的场景: 某些模块负责生产数据,这些数据由其他模块来负责处理(此处的模块可能是:函数.线程.进程等).产生数据的模块称为生产者,而处理数据的模块 ...
最新文章
- jmeter获取时间_time 函数
- java金字塔数字代码_Java基础代码实例 :在控制台中输出金字塔,这个金字塔是由左右对称的数字组成的。 | 学步园...
- 孙庆新:做产品,感觉从何而来
- syslog记录history历史记录
- CentOS7下Hive集群搭建
- boost::search相关的测试程序
- u-boot 源码分析讲解
- python如何操作oracle数据库_Python 操作 Oracle 数据库
- [vue] 删除数组用delete和Vue.delete有什么区别?
- layer 同步调用_关于Layer组件的同步以及减少GPU带宽的问题
- k-d tree算法原理及实现
- 1039. 到底买不买(20)-PAT乙级真题
- 检测到无效的异常处理程序例程。_异常控制流(1):异常概述和基本类型
- 解决cuda官网安装包下载速度慢的问题
- CS231n 课程笔记翻译
- 读取json本地js处理输出html,JavaScript 通过浏览器导出和读取本地 JSON 文件
- 编写一个生成器函数,能够生成斐波那契数列
- SAP-SD-ABAP-销售订单自动确认程序-AVAILABILITY_CHECK_S4-SD_BACKORDER_UPDATE
- JavaScript 如何求两个数的最小公倍数
- 左耳听风-Equifax信息泄露始末
热门文章
- C++ 之父讨厌比特币
- JavaScript 九种跨域方式实现原理 1
- 如何使用Visual Studio无需成本即可实现连续集成
- 不使用输入框如何实现下拉_使用INFINITE AJAX SCROLL实现下拉加载效果
- java转js_java对象转js对象
- js生成图片_网页骨架屏自动生成方案(dps)
- tiptop 编译运行_putty终于让我的TIPTOP脱离虚拟机在64位上运行了。
- div 高度等与html,html – 仅限CSS – 基于兄弟的div的高度
- css 入场动画_React系列十四 React过渡动画
- 最优阈值生长算法_手淘搜索阈值刻度表:让你更加清楚类目搜索增长的规律