zoukankan      html  css  js  c++  java
  • python的消息队列Queue的概念


     前言:

      我刚接触消息队列时,也是在网上百度搜索,发现好多博客写的有关消息队列Queue的时候,写的例子里都有多线程或者多进程的内容,把这些内容和Queue写在一起,我感觉如果是新手的话,是不太好理解的;因为从性能优化的角度来讲,消息队列也是为了分配任务,避免大量的并发请求过多过快的消耗服务器资源,从而优化产品的性能,这样的话,多线程或者多进程,又或者协程等等都是可以达到优化的目的,所以,我觉得在讲消息队列的内容时候,对于新手,还是不要涉及其他的内容比较好;

      在练习Queue的知识点时,我也有犯过些错误,比如说看了别人的博客,最后也实现了自己想要的效果,但是最后才反应过来,我写的代码,其实没有Queue也可以的,完全可以用Thread多线程来实现,而Queue的知识可以说是没有练习到,这也是我说上面一段话的背景;

      多线程和消息队列有什么相同和不同?

      相同点:都可以作为优化系统性能的方案;

      不同点:两者优化性能的方式不同,打个比方如下:

          1.比如用户访问登录接口,那么很多个用户同时访问该接口时,后台可以同一时刻为每一个用户单独起一个线程,让用户在最短时间内拿到登录结果,这也叫用户并发登录,这样对用户来说体验会好些,但是对系统来说,就很消耗资源,容易崩溃,这种场景用多线程比较合适(实际企业这样用的不多);

          2.再比如,测试人员经常要运行自动化案例,有时运行几个小时都结束不了,而且测试化境很复杂不好搭建,不能提拱并发执行,这时,可以考虑用消息队列了,每个人都可以在下班前提交一个测试任务,先提交的任务先运行,按顺序执行任务,等上一个测试任务执行完,再执行下一个的任务,像这种不要求立刻得到结果的场景,就可以考虑用消息队列了,说到这里,如果有需要了解学习自动化测试平台开发的小伙伴,欢迎和我交流,可以搜索并关注公众号“测试运维”,一起进步!

            3.最后,再打个比方来说明消息队列和多线程的区别,比如地铁站怎么处理客流高峰呢?一种方案是临时增加很多个刷卡通道并同时开放,使每个通道排队等候的人不多,这种方案可以让乘客很快进站,类似于多线程,这种方案对乘客来说是好事,减少了乘客的等待时间,但是对于地铁站来说就很难了,因为地铁站就那么大,不是想开几个通道就开几个,虽然技术上可以实现,但是不太现实;另一种方案,保持原有的刷卡通道个数不变,组织乘客排队刷卡进站,哪怕队已经排的很长很长,拐着弯排队,甚至是排到地铁站外面,只要大家都有序排队,最后都可以进站,这个方案就是类似消息队列,在队列管控上做改动,而不是在基础硬件设施上做改动,这种方案,对地铁站来说是好事,不用额外新建那么多通道,但是对乘客来说,等待的时间太长,体验不好; 

    一.先源码实现一下queue,参考网上的。


    class Queue(object): def __init__(self, max_item): self.queue = [] self.max_item = max_item def enqueue(self, item): for i in item: if len(self.queue) >= self.max_item: print('队列已满') return self.queue else: self.queue.append(i) return self.queue def dequeue(self): return self.queue.pop(0) def is_empty(self): return self.queue == [] def is_full(self): return len(self.queue) >= self.max_item def size(self): return len(self.queue) if __name__ == '__main__': queue = Queue(3) print(queue.enqueue([1,2,3,4])) #队列已满,[1, 2, 3] # print(queue.dequeue()) print(queue.is_full())

    二,Python内置的四种队列的类型 (本次写的是LILO)

    1. LILO
      先进先出,只能在尾部插入元素,只能从头部取出元素
    2. LIFO
      先进后出,类似栈
    3. 优先队列
      队列元素为元组类型,即(优先级,数据)。
    4. 双端队列

    三.常用的方法

    • q.task_done()    需要结合q.join来用,具体如下:

    1.如果用了q.join(),那就一定要通过写q.task_done() ,来通知q.join当前事件已完成, 不写q.task_done()的话,q.join收不到当前事件完成时的信号,还会阻塞在q.join执行的地方等待接收信号,join后的代码得不到正常执行;

    2. 同时不写q.join,和q.task_done() ,也是可以的,可以正常执行;
    3.  只写q.task_done()不写q.join也是可以的,可以正常执行;

    • q.join()   直到queue队列中的所有事件都处理完毕,队列为空以后再执行q.join()之后的代码,如果用了q.join(),那就一定要写q.task_done()

    • q.put(item[, block[, timeout]])    向队列中增加事件,  .可以利用put和get进行传参,   #注意这里如果有多个参数,要用键值对或字典

    • q.get( block[, timeout]])   执行队列中的事件,执行完后将该事件从队列中删除,并返回当前的事件
    • q.qsize() 返回队列的大小

    • q.empty() 如果队列为空,返回True,反之False

    • q.full() 如果队列满了,返回True,反之False,Queue.full 与 maxsize 大小对应
    • q.get_nowait() 相当于Queue.get(False),非阻塞方法
    • q.queue   返回当前队列中所有的任务
     

     四. 一些需要注意的细节

    • 入队列时堵塞

    from queue import Queue

    #设置队列长度为1
    que = Queue(maxsize=1)
    #此时如果入队列两次, put将会一直堵塞,等待前一个出队列
    que.put(1)
    que.put(2)
    • 入队列非堵塞
    from queue import Queue
    que = Queue(maxsize=1)
    #设置block为False为非堵塞,默认block为True堵塞

     try:

     
    que.put(1)
    #如果队列为满,非堵塞将会报异常
    que.put(2,block=False)
    except Exception:
    pass
     
    • 出队列堵塞
    from queue import Queue
    que = Queue(maxsize=2)
    que.put(1)
    que.get()
    que.get()
    #如果队列为空,get会一直等待
    • 出队列非堵塞
    from queue import Queue
    que = Queue(maxsize=2)
    que.put(1)
    que.get()
    try:
    #如果设置为非堵塞,将会报异常
    que.get(block=False)
    except Exception:
    pass
    • 设置超时

    from queue import Queue

    que = Queue(maxsize=1)
    que.put(1)
    try:
    #设置超时后,如果2秒后还不能进队列将会报异常
    #在非堵塞的情况下,无需设置超时
    que.put(2,timeout=2)
    except Exception:
    pass
    que.get()
    try:
    #设置超时后,如果2秒后队列仍是空将会报异常
    #在非堵塞的情况下,无需设置超时
    que.get(timeout=2)
    except Exception:
    pass
     
  • 相关阅读:
    C# 图形普通处理,resize ,水印..
    图像处理 形态学 (腐蚀 膨胀 开闭运算 连通分量....)
    获取usb设备父系或子代
    aforge通过角点匹配图片相似度
    CentOS 手动增加、删除swap区
    Zabbix 中文使用手册
    CentOS7下Firewall防火墙配置用法详解
    CentOS7安装Zabbix
    宅男也可变形男-我是如何在11个月零27天减掉80斤的
    CentOS环境下使用GIT基于Nginx的私服搭建全过程
  • 原文地址:https://www.cnblogs.com/ojbk6943/p/14420311.html
Copyright © 2011-2022 走看看