队列、生产消费模型.html
一、python 队列:
- 概述:
- import queue
- 都是在python内存中创建,python进程退出,则队列清空
- 可通过pycharm查看这些队列类的方法
- 先进先出队列:
- q = queun.Queue( [10] ) # 创建一个 "先进先出" 队列,最多接受10个数据,放第11个时会卡主,不加参数默认为0,即无限多个
- q.qsize() # 查看当前队列中元素个数
- q.maxsize # 队列最大个数
- q.put(33, [ timeout=2] ) # 等待2秒,若2秒过后还没有空余位置则报错
- q.put(33, [block=False]) # 默认是阻塞,且一直卡主等待,若为false则没有位置时直接报错
- q.get() # 默认取数据,若队列中已经没有元素,则会阻塞卡主
- q.get([block=False]) # 不阻塞,
- q.get(timeout=2) # 超时时间
- q.join() # 若队列中任务(获取和插入均为任务)还没有完成(不为空,且计数器归零),则主进程不结束,进行等待
- q.task_done() # 该代码常在每个队列方法执行后书写,表示该方法已经执行完成,计数器归零
- 后进先出队列(栈)(继承queue,即可用其父类中方法):
- q = queue.LifoQueue() # last in first out
- 优先级队列(继承queue):
- q = queue.PriorityQueue()
- q.put((11, 'alex')) # 放元素的时候,附带指定一个优先级,队列中会按照优先级重新排序
- 双向队列
- q = queue.deque()
二、生产者、消费模型(队列)
import queueimport timeq = queue.Queue(20) # 创建个先进先出队列# “生产者” 每个厨师都一直创建包子,直到队列满了阻塞,def productor(arg):while True:q.put(str(arg)+':包子') # 创建一个包子放入队列,厨师编号:包子# “消费者” 每个顾客都一直消费包子,直到队列空了阻塞def consumer(arg):while True:print(arg, q.get()) # 从队列拿出一个包子, 哪个厨师:包子time.sleep(2)
for i in range(3): # 创建3个厨师t = threading.Thread(target=productor, args=(i,))t.start()
for j in range(20): # 创建20个人t = threading.Thread(target=consumer, args=(,))t.start()
- 使用队列好处:
- 结论:
- 使用队列,可以增加client的并发处理,不至于client的请求都不能接受(拒绝服务)
- 要真正提高处理能力,还得增加后端工作线程
- 解释:
- 场景:server并发假设为4个,客户端均为动态请求(insert into ..),每个insert语句执行事件若为20s
- 不使用队列:
- 流程:
- server接到一个请求,立马拿来一个工作线程进行处理,处理过程中一直与client保持连接(连接处于挂起状态)
- 并发能力:20s,最多4个并发
- 请求处理:20s,4个工作线程可处理4个请求,1个工作线程只能处理一个(接进来的请求,没有人处理也是没卵用)
- 使用队列
- 流程:
- 当server接到用户请求后,直接丢进队列中,而后与client连接断开,
- 后端工作的线程(生产者)不断从队列中取出请求进行处理
- 当client再次查询上次请求执行结果,
- 若请求还在队列中,则返回队列位置“请求正在处理,您前面还有N个人”
- 若请求不在队列中,server只需要select下db即可返回(比insert快很多)
- 并发能力:无限,因为丢进队列后就可以断开连接,即总是有4个连接可用
- 请求处理:20s内,4个工作线程可处理4个请求,1个工作线程只能处理1个请求