threading模块和queue模块实现程序并发功能和消息队列
简介:
通过三个例子熟悉一下python threading模块和queue模块实现程序并发功能和消息队列。
说明:以下实验基于python2.6
基本概念
什么是进程?
拥有独立的地址空间,内存,数据栈以及记录其运行轨迹的辅助数据。它可以通过fork和spawn操作来完成其它任务。进程间只能使用IPC(进程间通信协议)共享信息。
什么是线程?
线程运行在一个主进程中,线程间共享相同的运行环境。只有在多cpu框架中线程才能发挥威力,单cpu中依然是顺序执行的。
注意问题:
-线程同时访问同一数据,可能导致数据结果不一致,(race condition)。大多数现场库有同步原语来控制线程的执行和数据访问。
-线程不可以直接kill,只能sys.exit()或者thread.exit()
示例一:threading模块实现多线程编程
threading_1.py
#!/usr/bin/env python
import threading
import datetime
class ThreadClass(threading.Thread):
def run(self):
now = datetime.datetime.now()
print"%s Hello KK at time: %s" % (self.getName(), now)
for i in range(2):
t = ThreadClass()
t.start()
运行结果:
我们启动了两个线程,所以看到两条输出。
Thread-1 Hello KK at time: 2012-12-22 20:13:40.150000
Thread-2 Hello KK at time: 2012-12-22 20:13:40.150000
解读:
重定义run方法,把自己的逻辑告诉线程。
getName()方法是threading模块中获取线程名用的。
for循环定义了我们将启动几个线程
start()启动线程。threading中等所有线程准备好后统一启动,而不是一个一个启动。
示例二:threading+Queue实现线程队列
threading_2.py
#!/usr/bin/env python
import Queue
import threading
import time
queue = Queue.Queue()
class ThreadNum(threading.Thread):
"""没打印一个数字等待1秒,并发打印10个数字需要多少秒?"""
def __init__(self, queue):
threading.Thread.__init__(self)
self.queue = queue
def run(self):
whileTrue:
#消费者端,从队列中获取num
num = self.queue.get()
print"i'm num %s"%(num)
time.sleep(1)
#在完成这项工作之后,使用 queue.task_done() 函数向任务已经完成的队列发送一个信号
self.queue.task_done()
start = time.time()
def main():
#产生一个 threads pool, 并把消息传递给thread函数进行处理,这里开启10个并发
for i in range(10):
t = ThreadNum(queue)
t.setDaemon(True)
t.start()
#往队列中填错数据
for num in range(10):
queue.put(num)
#wait on the queue until everything has been processed
queue.join()
main()
print"Elapsed Time: %s" % (time.time() - start)
运行结果:
i'm num 0
i'm num 1
i'm num 2
i'm num 3
i'm num 4
i'm num 5
i'm num 6
i'm num 7
i'm num 8
i'm num 9
Elapsed Time: 1.01399993896
解读:
具体工作步骤描述如下:
1,创建一个 Queue.Queue() 的实例,然后使用数据对它进行填充。
2,将经过填充数据的实例传递给线程类,后者是通过继承 threading.Thread 的方式创建的。
3,生成守护线程池。
4,每次从队列中取出一个项目,并使用该线程中的数据和 run 方法以执行相应的工作。
5,在完成这项工作之后,使用 queue.task_done() 函数向任务已经完成的队列发送一个信号。
6,对队列执行 join 操作,实际上意味着等到队列为空,再退出主程序。
在使用这个模式时需要注意一点:通过将守护线程设置为 true,程序运行完自动退出。好处是在退出之前,可以对队列执行 join 操作、或者等到队列为空。
示例三:多个队列
threading_3.py
#!/usr/bin/env python
import Queue
import threading
import time
queue = Queue.Queue()
out_queue = Queue.Queue()
class ThreadNum(threading.Thread):
"""bkeep"""
def __init__(self, queue, out_queue):
threading.Thread.__init__(self)
self.queue = queue
self.out_queue = out_queue
def run(self):
whileTrue:
#从队列中取消息
num = self.queue.get()
bkeep = num
#将bkeep放入队列中
self.out_queue.put(bkeep)
#signals to queue job is done
self.queue.task_done()
class PrintLove(threading.Thread):
"""Threaded Url Grab"""
def __init__(self, out_queue):
threading.Thread.__init__(self)
self.out_queue = out_queue
def run(self):
whileTrue:
#从队列中获取消息并赋值给bkeep
bkeep = self.out_queue.get()
keke = "I love " + str(bkeep)
print keke,
print self.getName()
time.sleep(1)
#signals to queue job is done
self.out_queue.task_done()
start = time.time()
def main():
#populate queue with data
for num in range(10):
queue.put(num)
#spawn a pool of threads, and pass them queue instance
for i in range(5):
t = ThreadNum(queue, out_queue)
t.setDaemon(True)
t.start()
for i in range(5):
pl = PrintLove(out_queue)
pl.setDaemon(True)
pl.start()
#wait on the queue until everything has been processed
queue.join()
out_queue.join()
main()
print"Elapsed Time: %s" % (time.time() - start)
运行结果:
I love 0 Thread-6
I love 1 Thread-7
I love 2 Thread-8
I love 3 Thread-9
I love 4 Thread-10
I love 5 Thread-7
I love 6 Thread-6
I love 7 Thread-9
I love 8 Thread-8
I love 9 Thread-10
Elapsed Time: 2.00300002098
解读:
ThreadNum 类工作流程
定义队列--->继承threading---->初始化queue---->定义run函数--->get queue中的数据---->处理数据---->put数据到另外一个queue-->发信号告诉queue该条处理完毕
main函数工作流程:
--->往自定义queue中扔数据
--->for循环确定启动的线程数---->实例化ThreadNum类---->启动线程并设置守护
--->for循环确定启动的线程数---->实例化PrintLove类--->启动线程并设置为守护
--->等待queue中的消息处理完毕后执行join。即退出主程序。
附1:threading模块对象
Thread 表示一个线程的执行对象
Lock 锁原语对象
RLock 可重入锁对象。使单线程可以再次获得已经获得了的锁
Condition 条件变量。可以让一个线程停下来等待满某个条件
Event 通用条件变量。多个线程同时等待某个事件,事件发生后激活所有线程
Semaphore 为等待锁的线程提供一个类似“候车室”的结构
BoundedSemaphore 与Semaphore类似,但它不运行超过初始值
Timer 与Thread相似,只是它要等待一段时间后才开始运行。
activeCount() 返回活动的线程对象的数量
currentThread() 返回当前线程对象
enumerate() 返回当前活动线程的列表
settrace(func) 为所有线程设置一个跟踪函数
setprofile(func) 为所有线程设置一个profile函数
附2:生产者-消费者模型
生产者把货物放入队列中,消费者消耗队列中的货物
queue模块就可以实现这个模型,实现线程间通信。
Queue模块函数:
queue(size) 创建一个大小为size的Queue对象
Queue对象函数:
qsize() 返回队列的大小,近似值
empty() 如果队列为空,则返回True。否则返回Fales
full() 呵呵,大家想一下就知道了。
put(item,block=0) 把item放到队列中,如果给了block且不为0,函数会一直阻塞到队列中有空间为止
get(block=0) 从队列中取一个对象,如果给了block且不为0,函数会一直阻塞到队列中有对象为止。
threading模块和queue模块实现程序并发功能和消息队列的更多相关文章
- Python并发编程之消息队列补充及如何创建线程池(六)
大家好,并发编程 进入第六篇. 在第四章,讲消息通信时,我们学到了Queue消息队列的一些基本使用.昨天我在准备如何创建线程池这一章节的时候,发现对Queue消息队列的讲解有一些遗漏的知识点,而这些知 ...
- Python并发编程-RabbitMQ消息队列
RabbitMQ队列 RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Public License开源协议. MQ全称为Message Queue, 消息队列 ...
- 高并发系统:消息队列MQ
注:前提是知道什么是消息队列.不懂的去搜索各种消息队列入门(activeMQ.rabbitMQ.rocketMQ.kafka) 1.为什么要使用MQ?(MQ的好处:解耦.异步.削峰) (1)解耦:主要 ...
- day43-python消息队列二-queue模块
Python提供了Queue模块来专门实现消息队列Queue对象 Queue对象实现一个fifo队列(其他的还有lifo.priority队列,这里不再介绍).queue只有maxsize一个构造参数 ...
- 消息队列(Message Queue)简介及其使用
消息队列(Message Queue)简介及其使用 摘要:利用 MSMQ(Microsoft Message Queue),应用程序开发人员可以通过发送和接收消息方便地与应用程序进行快速可靠的通信.消 ...
- 后台程序处理(二) python threading - queue 模块使用
由于协程没办法完成(一)中所说的任务模式 接下来就尝试一下使用线程和队列来实现一下这个功能 在实现之前,我们先明确一个问题--python的线程是伪并发的.同一时间只能有一个线程在运行.具体怎样的运作 ...
- Python进阶----异步同步,阻塞非阻塞,线程池(进程池)的异步+回调机制实行并发, 线程队列(Queue, LifoQueue,PriorityQueue), 事件Event,线程的三个状态(就绪,挂起,运行) ,***协程概念,yield模拟并发(有缺陷),Greenlet模块(手动切换),Gevent(协程并发)
Python进阶----异步同步,阻塞非阻塞,线程池(进程池)的异步+回调机制实行并发, 线程队列(Queue, LifoQueue,PriorityQueue), 事件Event,线程的三个状态(就 ...
- python-网络安全编程第六天(threading多线程模块&Queue模块&subprocess模块)
前言 昨天晚上9点多就睡了 2点起来没睡意... 那就学习吧emmmm ,拿起闲置几天的python课程学习.学习到现在5.58了 总结下 继续开始学习新的内容 多多线程? 线程(英语:thread) ...
- day09 threading, paramiko, queue 模块
1 模拟ssh 2 锁 内部锁,程序锁,信号量 3 多线程 4 简单消息队列 先来看模拟ssh ,python 的强大之处就是因为有很多模块,可以很简单的完成复杂的事情,今天我们用paramiko ...
随机推荐
- hdu 2080
ps:水题...求夹角...先求出COS,然后用acos 代码: #include "stdio.h" #include "math.h" int main() ...
- GSM Sniffing入门之硬件篇
3个月前,听朋友介绍得知OsmocomBB项目.此前一直以为GSM Sniffing需要价格昂贵的专用设备,但osmocomBB的上手成本:一个25元左右的手机,外加一根USB转TTL的串口线,着实让 ...
- hdu - 2083 - 简易版之最短距离
找到中位数 , 根据对称性 , 当中位数需要两个数取中值的时候不需要取 , 只需要其中的任意一个数几个 例如四个数 1 , 2 , 3 , 4 . 这四个数 , 其中的 2 和 3 都可以 . 然后求 ...
- Magento产品批量导入方法?
从事外贸的我们在工作中,经常需要添加成千上万个的产品,如果一个一个的去上传,要花费很多时间,有是很让人头痛,那么应该如何实现产品批量上传?如果使用的是Magento系统的话,那么你现在有福利了,因为M ...
- java学习第六天
目标 1. 块 2. GC(了解) 3. package import 4. 封装 一.块 {} 分类 1.普通块 作用: 组织代码.解决变量的作用域.节约了内存. 在同一个作用域内,不能声 ...
- cocos2d-html5版日历组件
根据一as3版本给改编成成了js版的.as3版本的地址: http://download.csdn.net/detail/fengye513/2722289 胜利项目做的差不多了,由于项目用的是c+ ...
- qemu源码架构
前言:本文主要概括了QEMU的代码结构,特别从代码翻译的角度分析了QEMU是如何将客户机代码翻译成TCG代码和主机代码并且最终执行的过程.并且在最后描述了QEMU和KVM之间联系的纽带. 申明:本文前 ...
- Examining Open vSwitch Traffic Patterns
In this post, I want to provide some additional insight on how the use of Open vSwitch (OVS) affects ...
- c#实现数据的左补右补功能
/// <summary> /// 左補右補功能 /// </summary> /// <param name="st ...
- 递归神经网络(RNN)简介(转载)
在此之前,我们已经学习了前馈网络的两种结构--多层感知器和卷积神经网络,这两种结构有一个特点,就是假设输入是一个独立的没有上下文联系的单位,比如输入是一张图片,网络识别是狗还是猫.但是对于一些有明显的 ...