美文网首页
Python的SimpleQueue

Python的SimpleQueue

作者: welder77 | 来源:发表于2022-10-30 18:30 被阅读0次

Queue是Python标准库中的线程安全的队列(FIFO先进先出)实现, 提供了一个适用于多线程编程的先进先出的数据结构,即队列,用来在生产者和消费者线程之间的信息传递。

Python 3.7版本开始添加了新功能SimpleQueue,SimpleQueue相比Queue简化了部分高级功能,拥有更好的性能表现。
在实际应用中,SimpleQueue的相应功能已可以满足大部分日常需求,所以推荐使用。

以下为SimpleQueue所拥有的功能:

  1. SimpleQueue.qsize()
    返回队列的大致大小。注意,qsize() > 0 不保证后续的 get() 不被阻塞。

  2. SimpleQueue.empty()
    如果队列为空,返回 True ,否则返回 False 。如果 empty() 返回 False ,不保证后续调用的 get() 不被阻塞。

  3. SimpleQueue.put(item, block=True, timeout=None)
    将 item 放入队列。此方法永不阻塞,始终成功(除了潜在的低级错误,例如内存分配失败)。可选参数 block 和 timeout 仅仅是为了保持 Queue.put() 的兼容性而提供,其值被忽略。

  4. SimpleQueue.put_nowait(item)
    相当于 put(item, block=False),为保持与 Queue.put_nowait() 的兼容性而提供。

  5. SimpleQueue.get(block=True, timeout=None)
    从队列中移除并返回一个项目。如果可选参数 block 是 true 并且 timeout 是 None (默认值),则在必要时阻塞至项目可得到。如果 timeout 是个正数,将最多阻塞 timeout 秒,如果在这段时间内项目不能得到,将引发 Empty 异常。反之 (block 是 false) , 如果一个项目立即可得到,则返回一个项目,否则引发 Empty 异常 (这种情况下,timeout 将被忽略)。

  6. SimpleQueue.get_nowait()
    相当于 get(False) 。

我们下面通过一个生产者消费者模式的案例来解释下SimpleQueue的用法。

假设我们有两个线程,一个线程专门用来接收CAN工具源源不断接收到的CAN报文(生产者线程),一个专门用来解析接收到CAN报文(消费者线程)。 由于生产者线程产生的CAN报文非常密集,所以有可能导致消费者线程来不及及时处理,所以我们通过队列来做缓存,防止漏帧。

from queue import SimpleQueue
import time, threading
import sys

# 生产者线程
def product(name):
    global finish_flag  #需要改写变量,需要加上global
    count = 1
    for n in range(100000):    #假设接收到了100000个报文
        sys.stdout.write(f"{name} 产生的帧:{count}\n")  # 打印产生的报文编号
        q.put(f"{name} 产生的帧:{count}")  # 将报文编号存入队列中
        count += 1
    finish_flag = True  #所有任务完成

# 消费者线程
def consume(name):
    while True:
        sys.stdout.write(f"{name} 获取了:{q.get()}\n")  # 获取队列中的一个报文编号,默认get不加参数,程序会处于阻塞状态,直到队列中有数据。
        if finish_flag and q.empty():   #当生产者线程完成所有任务,同时队列也为空时退出
            break


if __name__ == "__main__":
    # 初始化报文的消息队列
    q = SimpleQueue()
    finish_flag = False
    can_rec = threading.Thread(target=product, args=('can工具',))
    can_analysis = threading.Thread(target=consume, args=('can解析器',))


    # 开启线程,并等待其执行完毕。
    t1=time.time()
    can_rec.start()
    can_analysis.start()
    can_rec.join()
    can_analysis.join()
    print(time.time()-t1)

总结,日常应用中,对于有密集数据接收的情况,比如CAN, Lin报文,接口数据都可以使用Queue做缓存来防止数据丢失。
Queue和SimpleQueue因为其线程安全的特性,对于线程的读写是非常友好的,也不需要担心线程间的干扰。
但使用时也需要注意,一旦使用了队列,其原有数据序列间的间隔是无法保存的,比如CAN报文的周期是无法通过队列进行还原的,所以通常存入数据序列的数据我们会为其加上时间戳,以记录其原有时序。

相关文章

网友评论

      本文标题:Python的SimpleQueue

      本文链接:https://www.haomeiwen.com/subject/jcvctdtx.html