Python 消息队列、多线程、多进程、协程(二)
本章内容简介
1. queue 消息队列详解:常用参数、队列的四种类型及实例;
2. Python 多线程: 线程池、线程锁
3. Python 多进程: 进程锁、进程池、数据共享
4. 协程
一. queue 消息队列
1)常用参数:
a = queue.Queue() #括号里是可以放几个数据,2就是2个;多的就放不进去了
a.put(11) # put放数据时,可以设置是否阻塞,超时时间
a.put(22)
a.get() # 取数据,按模式取值,默认(阻塞);可以设置参数(block=False),超时时间(timeout=2)2秒;
a.qsize() # 计数,列队里有几个值;
a.task_done() # 标识列队里的此任务已经完成了,和join配合使用;
a.join() # 如果列队没执行完,程序不终止,执行完要告诉队列,执行完了,才能终止操作。
2)队列的四种模式:
# queue.Queue,先进先出队列
# queue.LifoQueue,后进先出队列
# queue.PriorityQueue,优先级队列
# queue.deque,双向对队
实例:

import queue # q = queue.Queue(2) 先进先出队列 # q = queue.LifoQueue() 后进先出队列 # q = queue.PriorityQueue() 优先级队列 # q = queue.deque() 双向队列 q = queue.LifoQueue() q.put(123) q.put(456) # 打印;456 print(q.get()) # 优先级最小的拿出来 # 如果优先级一样,则是谁先放,就先取出谁 q = queue.PriorityQueue() q.put((1,'alex1')) q.put((1,'alex2')) q.put((1,'alex3')) q.put((3,'alex3')) # (1, 'alex1') print(q.get()) q = queue.deque() q.append(123) q.append(333) q.appendleft(456) # deque([456, 123, 333]) print(q) # 打印:456 print(q[0]) q.pop() # 从右边删除 # deque([456, 123]) print(q) q.popleft() # 从左边删除
3)队列(生产者消费者模型)
1)生产者消费者模型的作用:
1、解决阻塞
2、就是解耦,修改生产者,不会影响消费者,反之亦然。
2)在生产环境,用生产者消费者模型,就可以解决:
1、处理瞬时并发的请求问题。瞬时的连接数就不会占满。所以服务器就不会挂了。
2、客户端提交一个请求,不用等待处理完毕,可以在页面上做别的事情。
2.1)如果不用队列存数据,服务端通过多线程来处理数据:
用户往队列存数据,服务器从队列里取数据。
没有队列的话,就跟最大连接数有关系,每个服务器就有最大连接数。
客户端要获取服务器放回,服务器要查、修改数据库或修改文件,要2分钟,那客户端就要挂起链接2分钟,2万个连接一半都要挂起,服务器就崩溃了。
如果没有队列,第一个用户发来请求,连上服务器,占用连接,等待2分钟。
第二个人来也要占用2分钟。
web服务器
如果要处理并发,有10万并发,如果:一台机器接收一个连接,需要10万个机器,等待2分钟就处理完了。
2.2)把请求放在队列的好处
用户发来请求,把请求放到队列里,可以让连接马上断开,不会阻塞,就不占用服务器的连接数了。如果看到订单处理了没,就要打开另外一个页面,查看请求是否处理。
服务器查询处理任务的时候,每个才花2分钟,服务器耗时是没有减少的。
但是这样做,客户端就不会持续的占用连接了。那瞬时的连接数就不会占满。所以服务器就不会挂了。
但是后台要处理10万个请求,也需要50台服务器。并不会减少服务器数量。
这样就能处理瞬时并发的请求问题。
服务器只是处理请求,是修改数据库的值,不是告诉客户端。而是客户端再发来请求,查询数据库已经修改的内容。
提交订单之后,把这个订单扔给队列,程序返回“正在处理”,就不等待了,然后断开这个连接,你可以在页面里做别的事情,不用一直等待订单处理完。这样就不影响服务器的最大连接数。在页面帮你发起一个alax请求,url,不停的请求(可能是定时器),我的订单成功没有,我的订单成功没有,如果订单成功了,就自动返回页面:订单成功
如果不用队列的话,一个请求就占用一个服务器,等待的人特别多,等待连接的个数太多了。服务器就挂掉了。
队列就没有最大个数限制,把请求发给队列了,然后http链接就断开了,就不用等待了。
12306买票的时候,下次再来请求的时候,就会告诉你,前面排了几个人。
3)python queue的特点:
python的queue是内存级别的。rabbitmq可以把队列发到别的服务器上处理。
所以python里的queue不能持久化,但是rabbitmq可以持久化。
queue.Queue()这样写,队列就没有最大个数限制。queue.Queue(5)就是说队列里最多能放5个值
4)生产者消费者代码示例:

import time,random import queue,threading q = queue.Queue() def Producer(name): count =0 while True: time.sleep(random.randrange(3)) if q.qsize()<3: # 只要盘子里小于3个包子,厨师就开始做包子 q.put(count) print("Producer %s has produced %s baozi.." %(name,count)) count += 1 def Consumer(name): count =0 while True: time.sleep(random.randrange(4)) if not q.empty(): # 只要盘子里有包子,顾客就要吃。 data = q.get() print(data) print('