thread 4, queue
来源:互联网 发布:网络维护难点分析 编辑:程序博客网 时间:2024/06/05 11:41
Queue队列
前期唠叨:
1.多线程采用的是分时复用技术,即不存在真正的多线程,cpu做的事是快速地切换线程,以达到类似同步运行的目的,因为高密集运算方面多线程是没有用的,但是对于存在延迟的情况(延迟IO,网络等)多线程可以大大减少等待时间,避免不必要的浪费。
2.原子操作:这件事情是不可再分的,如变量的赋值,不可能一个线程在赋值,到一半切到另外一个线程工作去了……但是一些数据结构的操作,如栈的push什么的,并非是原子操作,比如要经过栈顶指针上移、赋值、计数器加1等等,在其中的任何一步中断,切换到另一线程再操作这个栈时,就会产生严重的问题,因此要使用锁来避免这样的情况。比如加锁后的push操作就可以认为是原子的了……
3.阻塞:所谓的阻塞,就是这个线程等待,一直到可以运行为止。最简单的例子就是一线程原子操作下,其它线程都是阻塞状态,这是微观的情况。对于宏观的情况,比如服务器等待用户连接,如果始终没有连接,那么这个线程就在阻塞状态。同理,最简单的input语句,在等待输入时也是阻塞状态。
4.在创建线程后,执行p.start(),这个函数是非阻塞的,即主线程会继续执行以后的指令,相当于主线程和子线程都并行地执行。所以非阻塞的函数立刻返回值的~
对于资源,加锁是个重要的环节。因为python原生的list,dict等,都是not thread safe的。而Queue,是线程安全的,因此在满足使用条件下,建议使用队列。
2.原子操作:这件事情是不可再分的,如变量的赋值,不可能一个线程在赋值,到一半切到另外一个线程工作去了……但是一些数据结构的操作,如栈的push什么的,并非是原子操作,比如要经过栈顶指针上移、赋值、计数器加1等等,在其中的任何一步中断,切换到另一线程再操作这个栈时,就会产生严重的问题,因此要使用锁来避免这样的情况。比如加锁后的push操作就可以认为是原子的了……
3.阻塞:所谓的阻塞,就是这个线程等待,一直到可以运行为止。最简单的例子就是一线程原子操作下,其它线程都是阻塞状态,这是微观的情况。对于宏观的情况,比如服务器等待用户连接,如果始终没有连接,那么这个线程就在阻塞状态。同理,最简单的input语句,在等待输入时也是阻塞状态。
4.在创建线程后,执行p.start(),这个函数是非阻塞的,即主线程会继续执行以后的指令,相当于主线程和子线程都并行地执行。所以非阻塞的函数立刻返回值的~
对于资源,加锁是个重要的环节。因为python原生的list,dict等,都是not thread safe的。而Queue,是线程安全的,因此在满足使用条件下,建议使用队列。
队列使用:
LifoQueue后入先出(LIFO)队列
PriorityQueue 优先队列
此模块一般用于和多线程配合
1.Queue.qsize() 返回队列的大小
2.Queue.empty() 如果队列为空,返回True,反之False
3.Queue.full() 如果队列满了,返回True,反之False
4.Queue.get([block[, timeout]]) 获取队列,timeout等待时间
5.Queue.get_nowait() 相当Queue.get(False)
6.非阻塞 Queue.put([block[, timeout]]) 写入队列,timeout等待时间
7.Queue.put_nowait(item) 相当Queue.put(item, False)
8.Queue.task_done() 每次从queue中get一个数据之后,当处理好相关问题,最后调用该方法,主要与q.join配合使用,以提示q.join是否停止阻塞
9Queue.join(): 实际上意味着等到队列为空,再执行别的操作,阻塞,直到queue中的数据均被删除或者处理。为队列中的每一项都调用一次
快速消费者的例子
import Queue,threading,time,randomclass consumer(threading.Thread): def __init__(self,que): threading.Thread.__init__(self) self.daemon = False self.queue = que def run(self): while True: if self.queue.empty(): break item = self.queue.get() #processing the item time.sleep(item) print self.name,item self.queue.task_done() returnque = Queue.Queue()for x in range(10): que.put(random.random() * 10, True, None)consumers = [consumer(que) for x in range(3)]for c in consumers: c.start()que.join()可以看到,生产者首先将队列准备好,然后消费者再使用。
最后只要使用que.join即可在queue为空的时候,停止三个进程;此时主线程即可退出。
快速消费者例子
import Queue,threading,time,random class consumer(threading.Thread): def __init__(self,que): threading.Thread.__init__(self) self.daemon = False self.queue = que def run(self): while True: item = self.queue.get() if item == None: break #processing the item print self.name,item self.queue.task_done() self.queue.task_done() return que = Queue.Queue() consumers = [consumer(que) for x in range(3)] for c in consumers: c.start() for x in range(10): item = random.random() * 10 time.sleep(item) que.put(item, True, None) que.put(None) que.put(None) que.put(None) que.join()这是一个快速消费者的例子,首先,由于队列中开始没有任何数据,所以无法使用上面的empty确认退出run;如果使用了empty语句,则虽然三个子线程都已经退出,但是主线程会卡到que.join这里,因为队列中存在了10个元素。
所以这里引入了None;使用None作为结束判断。
当然也可以把子线程设置为deamon,一但生产完成,开始que.join()阻塞直至队列空就结束主线程,子线程虽然在阻塞等待队列也会因为deamon属性而被强制关闭。。。。
生产者消费者通用例子
#encoding=gbk import threading import time condition = threading.Condition() products = 0 class Producer(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): global condition, products while True: if condition.acquire(): if products < 10: products += 1; print "Producer(%s):deliver one, now products:%s" %(self.name, products) condition.notify() else: print "Producer(%s):already 10, now products:%s" %(self.name, products) condition.wait() condition.release() time.sleep(2) class Consumer(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): global condition, products while True: if condition.acquire(): if products > 1: products -= 1 print "Consumer(%s):consume one, products:%s" %(self.name, products) condition.notify() else: print "Consumer(%s):only 1, stop consume" %(self.name) condition.wait() condition.release() time.sleep(2) if __name__ == "__main__": for p in range(0, 2): p = Producer() p.start() for c in range(0, 10): c = Consumer() c.start()
最后,queue是线程安全的,但不是进程安全的,多进程情况下可以使用multiprocessing.Queue()
0 0
- thread 4, queue
- windows, thread ,message queue
- Thread safe circular queue
- A Thread's Message Queue
- Exception processing async thread queue
- Exception processing async thread queue
- Exception processing async thread queue
- Exception processing async thread queue
- Exception processing async thread queue
- Exception processing async thread queue
- Exception processing async thread queue
- Python多线程:thread、threading、queue
- main Queue 与 main Thread
- Proceess,Pool中的Queue通讯以及Thread中的Queue
- 解决 Exception processing async thread queue
- python多线程模块thread,threading,Queue
- 调试 Exception processing async thread queue问题
- android thread Handler 、Looper、 Message、 Message Queue
- 黑马程序员_博客说明
- 关于自己经历的一个项目的杂谈
- linux 多线程
- K60系列学习(四)Start.s启动代码分析
- Group by与having理解
- thread 4, queue
- UVa 10267 Problem: Graphical Editor (PC 110105)
- ACM HDOJ 1042 (N!)
- 堆排序
- android系统如何自适应屏幕大小
- 36条微信公众账号运营的心得总结
- pc指针与流水线的关系
- TCP连接释放
- What is an ORA-600 Internal Error? (文档 ID 146580.1)