今天我们来了解一下python的队列(Queue)
queue is especiall useful in threaded programming when information must be exchanged safely between multiple threads.
队列就是一个有顺序的容器,可以靠顺序把他分成这几类。
FIFO队列和LIFO队列
FIFO,即first in first out ,数据是先进先出,而LIFO队列是last in first out ,数据后进先出。
class queue.Queue(maxsize=0) #先进先出 class queue.LifoQueue(maxsize=0) #后进先出 class queue.PriorityQueue(maxsize=0) #存储数据时可设置优先级
所以说队列的效果和列表的效果是一致的。但是最直接的区别是从列表里取数后数据还在列表内,而队列是取出一个数据就少了一个。
优先级队列的用法:


1 q = queue.PriorityQueue() 2 q.put((0,'a')) 3 q.put((2,'b')) 4 q.put((1,'c')) 5 print(q.get()) 6 print(q.get()) 7 print(q.get())
所以,优先级的队列是把数据按照元组的方式存在队列里,然后依据元组第0个数据的大小取出数据


(0, 'a') (1, 'c') (2, 'b')
队列的基本用法
1.数据操作
import queue q = queue.Queue(maxsize=5) #实例化队列 q.put(item=,block=,timeout=) #数据入队列 q.get(block=,timeout=) #数据出队列
在数据进出队列时,block默认值为True,即如果在定义队列的时候定义了队列的大小,如果队列溢出后在向队列里放数据后会阻塞,直到有数据出队列才会放行。
同理,如果get的时候队列已经空了,也会阻塞,直到有数据进队列。
如果想避开这个阻塞,我们可以在put和get的时候加上timeout的值,或者把block值设为false,数据量超出就会抛出full或empty的异常,然后进行相关操作。
另外还有个另外的用法是这样的
q.get_nowait() #数据出队列(不阻塞) q.put_nowait() #数据入队列(不阻塞)
在用nowait的方式操作队列时,程序不会阻塞,只会弹出相应的错误,我们可以用try来抓取异常后进行相关的动作。
2.队列的判定
q.empty() #判定队列是否为空 q.full() #判定队列是否溢出
输出为True或False。
队列的作用:
1.提高程序的效率。客户端可以不用等待数据的处理,只把数据仍在队列里等待处理完成后取出即可。
2.可以通过队列降低生产者和消费者之间的关系,起到程序解耦的作用,消费者或生产者只和队列有关联,而没有直接的关系。
生产——消费者模型。
在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。
为什么要使用生产者和消费者模式
在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。
什么是生产者消费者模式
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
在这里引申出这个模型,因为最基础的生产消费者模型是基于队列工作的。
让我们看一下最简单的一个生产消费者模型:
在一个数据采集系统中,可以把DAQ看作是生产者,所有原始的数据都是DAQ来产生的,我们把DAQ放在一个线程内,采集获得的数据存入队列,对数据的分析、处理可以看作消费者,消费者不断从队列里将数据取出。


1 import threading,queue 2 import random,time 3 def analog_in(): #生成随机信号 4 data = random.randint(4000,20000) 5 data= data/1000 6 return data 7 8 def DAQ_Producer(): 9 i =1 10 while True: 11 data = analog_in() 12 data_queue.put(data) 13 time.sleep(0.5) 14 print('get %s data:%s'%(i,data)) 15 i+=1 16 def DAQ_customer(): 17 while True: 18 elec_singal = data_queue.get() 19 pressure = (elec_singal-4)/16*10 20 time.sleep(0.5) 21 print('pressure is %.3f MPa.'%pressure) 22 23 data_queue=queue.Queue(maxsize=10) 24 25 t = threading.Thread(target=DAQ_Producer,) 26 t.start() #get data 27 28 c = threading.Thread(target=DAQ_customer,) 29 c.start() #data processing
我们用随机数生成一个4~20mA的电流信号,假设压力变送器满量程为10MPa,可以按照2semples/s的采样速率对信号进行采集。