Python35 events(事件)、队列
2018-03-15 21:16
281 查看
事件(events)
基于event实现绿灯举例的多线程 程序 import time import threading event = threading.Event() def lighter(): count = 0 event.set() ##先设置标志位为真,表示初始状态就是绿灯。否则当下面的if count > 5之前,标志位都是没有被设置的 while True: if count > 5 and count <10: #大于5并且小于10就改成红灯 # 这里代码不能只写成if count > 5,因为只要满足大于5,就不会去匹配大于10的elif条件了。 event.clear() #把标志位清空,检查标志位,如果标志位没有被设置,则当做红灯。 print ("\033[41;1m red light is on...\033[0m") ## 这里>5 and <10的数是6-9,所以这里会打印红灯4次。 elif count > 10: #红灯到绿灯期间设置时间为10秒,当大于30时,设置标志位 event.set() #设置标志位,检查到这个标志位,就当做已经绿灯 count = 0 #用count来计数多少秒,当设置为绿灯时就清空为0秒,20秒后就红灯 else: print("\033[42;1m green light is on...\033[0m") ## 匹配count既不大于5,也不大于10时(也就是小于5时),打印绿灯亮 ## 这里0-5会打印绿灯6次。 time.sleep(1) #设置每一秒循环一次,这样20秒后就红灯,20秒到30秒后就变成绿灯。 count += 1 def car(name): while True: if event.is_set(): #这里判断如果事件设置了标志位(表示绿灯) print ("[%s] running..." %name) time.sleep(1) else: #标志位为空表示红灯 print ("[%s] sees red light, waiting......" %name) event.wait() #如果判断标志位为空,则阻塞程序,直到标志位为真。 print ("[%s] green light is on, start going... "%name) light = threading.Thread(target=lighter,) light.start() car1 = threading.Thread(target=car,args=("car1",)) car1.start()
执行结果:
可以看到绿灯时,车就正常行驶; 红灯时就等待。
队列(queue)
FIFO(先进先出)
队列的作用:
1、解耦:避免两者之间的过度依赖,以免其中一方出现问题,另一方不能再执行。
2、效率:增加数据处理的效率。
队列可以理解为一个容器,用来放数据的,不过这个容器中的数据是有顺序的。
import queue q = queue.Queue() #先生成一个队列对象 q.put("d1") #将d1这个数据放入队列中 q.put("d2") #将d2这个数据也放入队列中 q.put("d3") q.qsize() # 来查询当前队列数据数量 print (q.get()) #这里不能取出指定的数据,只能根据先进先出的顺序来取出数据,所以这里取出的是"d1"这个数据 print (q.get()) #这里取出的是"d2"这个数据 print (q.get()) #这里取出的是"d3"这个数据 执行结果: d1 d2 d3 ## 先进先出的顺序来get数据
10办公
import queue q = queue.Queue() q.put("d1") q.put("d2") q.put("d3") q.qsize() print (q.get()) print (q.get()) print (q.get()) print (q.get()) ## 之前只进入了3个数据,且3个数据也被取出了,此时数据为空,我再次取数据就会卡在这,因为没有数据了,会一直卡在这等待新的数据进来 执行结果:
可以看到程序卡主了。
import queue q = queue.Queue() q.put("d1") q.put("d2") q.put("d3") q.qsize() print (q.get()) print (q.get()) print (q.get()) print (q.get(block=False)) ## 默认就存在block=True这个参数,True的话表示如果数据为空就卡主,设置False就不卡主
不在卡主,并且抛出异常
import queue q = queue.Queue() q.put("d1") q.put("d2") q.put("d3") q.qsize() print (q.get()) print (q.get()) print (q.get()) print (q.get(timeout=3)) ## 设置如果卡主的话,卡多久,这里设置为卡3秒
卡3秒后,依然没有数据进来,会抛出异常。
import queue q = queue.Queue() q.put("d1") q.put("d2") q.put("d3") q.qsize() print (q.get()) print (q.get()) print (q.get()) print (q.get_nowait()) ## 使用get_nowait()来取数据,如果取的数据是空就会抛出异常。
可以使用try,except异常来使用get_nowait()来解决获取空数据的问题;
也可以使用if q.qsize()来判断==0的话,就是空数据,然后在做下一步操作。
import queue q = queue.Queue(maxsize=3) ## 设置队列中最多可以有多少个数据 q.put("d1") q.put("d2") q.put("d3") q.put("d4") ##因为设置最有能有3个数据,当我们设置第4个数据的时候前三个数据还没有取出,就会卡主 ##可以设置多个线程,边放边取数据,就不会卡主了。
import queue q = queue.Queue(maxsize=3) q.put("d1") q.put("d2") q.put("d3") q.put("d4",block=False,timeout=3) ## put也支持block和timeout
Lifo (last in first out 后进先出)
一般场景都是先入先出,后入先出的情况比较少。
卖水果就可以实现后入先出的场景,因为后来的水果比较新鲜,所以就先卖出去的快。
import queue q = queue.LifoQueue() q.put(1) q.put(2) q.put(3) print (q.get()) print (q.get()) print (q.get()) 执行结果: 3 2 1
PriorityQueue(优先级队列)
存储数据时可以设置优先级队列
import queue q = queue.PriorityQueue() q.put((10,"Amy")) q.put((-1,"Peter")) q.put((3,"Zhangsan")) q.put((6,"lisi")) print (q.get()) print (q.get()) print (q.get()) print (q.get()) 执行结果: (-1, 'Peter') #优先级最高 (3, 'Zhangsan') (6, 'lisi') (10, 'Amy') #优先级最低 ##将数字放在前面就按照数字越小,越优先出 ## 也可以按照字母等顺序来排列。
生产者消费者模型
假如生产者是视频服务器,消费者是用户,用户消费(看视频),将请求转到后台服务器,生产者处理、提供视频数据。
但是消费者并不关心你后台提供了多少台服务器,所以这种模型解耦比较好。
import threading,time import queue q = queue.Queue() def Producer(name): for i in range(10): q.put("骨头%s"%i) ##生产10个骨头 def Consumer(name): while q.qsize() > 0: #判断队列还有数据就循环 print ("[%s]取到[%s]并且吃了它..."%(name,q.get())) #消费骨头 p = threading.Thread(target=Producer,args=("LiSi",)) c = threading.Thread(target=Consumer,args=("Dog",)) p.start() c.start() 执行结果: [Dog]取到[骨头0]并且吃了它... [Dog]取到[骨头1]并且吃了它... [Dog]取到[骨头2]并且吃了它... [Dog]取到[骨头3]并且吃了它... [Dog]取到[骨头4]并且吃了它... [Dog]取到[骨头5]并且吃了它... [Dog]取到[骨头6]并且吃了它... [Dog]取到[骨头7]并且吃了它... [Dog]取到[骨头8]并且吃了它... [Dog]取到[骨头9]并且吃了它... ## 生产了10个骨头,都被dog给吃了。
import threading,time import queue q = queue.Queue(maxsize=10) #最大放入十个骨头 def Producer(name): count = 1 while True: #为了持续性的生产骨头,这里使用while。 q.put("骨头%s"%count) ##当骨头超过10个的时候,就卡主了,直到骨头被取出少于10时循环放骨头进来 print ("生产了骨头%s"%count) count += 1 time.sleep(2) #两秒生产1个 def Consumer(name): while True: #这里设置True,而不是>0,因为刚生产1个被吃掉的话,就不大于0了,dogs就不会再吃骨头 print ("[%s]取到[%s]并且吃了它..."%(name,q.get())) time.sleep(1) #这里设置每秒吃1个骨头但是因为生产的慢(2秒生产1个),所以就吃的慢。 p = threading.Thread(target=Producer,args=("LiSi",)) c1 = threading.Thread(target=Consumer,args=("Dog1",)) c2 = threading.Thread(target=Consumer,args=("Dog2",)) p.start() c1.start() c2.start() 执行结果: 生产了骨头1 [Dog1]取到[骨头1]并且吃了它... 生产了骨头2 [Dog2]取到[骨头2]并且吃了它... 生产了骨头3 [Dog1]取到[骨头3]并且吃了它... 生产了骨头4 [Dog2]取到[骨头4]并且吃了它... 生产了骨头5 [Dog1]取到[骨头5]并且吃了它... 生产了骨头6 [Dog2]取到[骨头6]并且吃了它... ........
def Producer(name): count = 1 while True: q.put("骨头%s"%count) print ("生产了骨头%s"%count) count += 1 time.sleep(0.5) #现在0.5秒生产1个,相当于1秒生产2个 def Consumer(name): while True: print ("[%s]取到[%s]并且吃了它..."%(name,q.get())) time.sleep(1) ##因为生产的快,两个线程就吃的快(每个线程每隔1秒吃一个) ##两个线程相当于1秒能吃2个,刚好与生产速度持平; ##如果生产过快的话,就是生产大于消费的速度了。 p = threading.Thread(target=Producer,args=("LiSi",)) c1 = threading.Thread(target=Consumer,args=("Dog1",)) c2 = threading.Thread(target=Consumer,args=("Dog2",)) p.start() c1.start() c2.start() 执行结果: 生产了骨头1 [Dog1]取到[骨头1]并且吃了它... 生产了骨头2 [Dog2]取到[骨头2]并且吃了它... 生产了骨头3 [Dog1]取到[骨头3]并且吃了它... 生产了骨头4 [Dog2]取到[骨头4]并且吃了它... 生产了骨头5 [Dog1]取到[骨头5]并且吃了它... ## 生产者消费者模型解决了解耦(生产和消费各干各的)、排队的问题(只要生产的资源够,消费者不需要排队)。
相关文章推荐
- Python笔记day40(并发)|守护线程、线程锁、信号量、事件、条件、定时器、队列、线程池
- python多进程笔记2 - 进程间通信:队列,管道,文件,共享内存,信号量,事件,互斥锁,socket
- python-异步回调-线程队列-线程事件-greenlet-协程
- UIView的Touch事件UIControlEvents详解
- 触摸事件 - UIControlEvents
- Python数据结构与算法之使用队列解决小猫钓鱼问题
- android 在ViewGroup中处理触摸事件 [Managing Touch Events in a ViewGroup]
- Python笔记——几种数据结构的实现:栈、队列及二叉树
- 添加自定义事件以及对osg事件队列的简单理解
- leetcode_107. Binary Tree Level Order Traversal II 二叉树层次遍历,利用python的list特性实现队列功能
- 03-python文件(文件夹复制练习)------使用递归遍历,广度遍历(队列),深度遍历(栈)
- Python实现具备元素唯一性的队列
- AndroidAnnotations——Listening to AdapterViewEvents监听适配器视图事件
- Python的Socket知识7:队列、生产者消费者模型
- Python队列服务 Python RQ Functions from the __main__ module cannot be processed by workers.
- python数据结构之队列
- Python 学习入门(35)—— 模块
- python 堆、队列操作、字符串格式化输出、字符串常用函数 示例代码
- Python中线程的MQ消息队列实现以及消息队列的优点解析
- python多线程编程(6): 队列同步