Python的Quene模块中提供了同步的,线程安全的队列类,包括 -
- FIFO(先进先出)队列
Queue, - LIFO(先进后出)队列
LifoQueue, - 优先级队列
PriorityQueue
这些队列都实现了锁原语,能够在多线程中直接使用,可以使用列表来实现线程间同步;
初始化Queue()对象时,如果(q=Queue(),若括号中没有指定最大可接受的消息数量,或者数量为负值,那么代表可接受的消息数量没有上限)
队列的方法:
put(self,item,block=True,time=None) #给队列中添加数据
get(self,block=True,timeout=None) #从队列中获取数据
- 如果队列满了,默认一直等待,
- timeout时间设置等待时间,后超过时间会报错,
- block设置为False就会不等待;和put_nowait方法一样
并且超过设置数量或者取出数量后都会报错;
基本FIFO队列(先进先出)
FIFO即First in First Out,先进先出。Queue提供了一个基本的FIFO容器,使用方法很简单,maxsize是个整数,指明了队列中能存放的数据个数的上限。一旦达到上限,插入会导致阻塞,直到队列中的数据被消费掉。如果maxsize小于或者等于0,队列大小没有限制。
from queue import Queue
q = Queue(5) #创建队列对象
for i in range(5):
q.put(i) #给队列中添加数据
while not q.empty(): #判断是否为空
print(q.get())#从队列中取出数据
运行结果:
0
1
2
3
4
如果队列中数据已满,继续添加数据会报错,同样如果已空,继续取数据也会报错;
from queue import Queue
q = Queue(4) #创建队列对象
for i in range(5):
q.put(i,block=False) #给队列中添加数据和q.no_wait类似
运行结果:
Traceback (most recent call last):
File "E:/workspace/python/pythonDemo/0911/queueDemo.py", line 6, in <module>
q.put(i,block=False) #给队列中添加数据
File "D:\softwore\Python\lib\queue.py", line 136, in put
raise Full
queue.Full
常用方法:
- q.full() 判断是否已满
- q.empty() #判断是否为空
- q.qsize() #输出元素个数
from queue import Queue
q = LifoQueue(5) #创建队列对象
for i in range(5):
q.put(i,block=False) #给队列中添加数据
print(q.full()) #判断队列是否已满
print('队列中元素个数为:',q.qsize())
while not q.empty(): #判断是否为空
print(q.get())#从队列中取出数据
print(q.empty()) #判断队列是否为空
print('队列中元素个数为:',q.qsize())
join()方法和task_done()
阻塞调用线程,直到队列中的所有任务被处理掉。.join() 实际上意味着等到队列为空,再执行别的操作,没有执行task_done(),则join无法判断队列到底有没有结束,在最后执行个join()是等不到结果的,会一直挂起。
只要有数据被加入队列,未完成的任务数就会增加。当消费者线程调用task_done()(意味着有消费者取得任务并完成任务),未完成的任务数就会减少。当未完成的任务数降到0,join()解除阻塞。从而执行主线程。
from queue import Queue
q = Queue(5)
q.put(1)
q.put(2)
q.put(3)
q.put(4)
print('------4-------')
q.put(5)
print('-----5------')
q.put(6)
print('-----6------')
运行结果:
------4-------
-----5------
原本超出设定的队列满了之后会一直等待,停滞后面的都不会运行;
from queue import Queue
q = Queue(5)
q.put(1)
q.put(2)
q.put(3)
q.put(4)
print('------4-------')
#等待队列中的任务执行完,没有告诉它,会一直认为没执行完
q.join()
q.put(5)
print('-----5------')
q.put(6,block=True)
print('-----6------')
运行结果:
------4-------
发现后面的并未执行;因为此刻的以为没有执行完,所以会一直等待,直到tesk_done告诉它已经执行完毕才可以;
from queue import Queue
q = Queue(5)
q.put(1)
q.put(2)
q.put(3)
#q.put(4)
print('------4-------')
q.task_done()
q.task_done()
q.task_done()
#q.task_done()
#等待队列中的任务执行完,没有告诉它,会一直认为没执行完
q.join()
q.put(5)
print('-----5------')
q.put(6,block=True)
print('-----6------')
运行结果:
------4-------
-----5------
-----6------
上面需要使用q.task_done()来声明任务已执行完,但是只加一个是不行的,之前给队列中添加了几个数据也就是使用了几次put,就需要使用几次task_done(),使用多了会报错;
Python提供线程安全的FIFO队列,初始化时可设置最大消息数量。队列满时插入数据会阻塞,空时取出数据也会阻塞。常用方法包括q.full()、q.empty()和q.qsize()。join()方法会阻塞,直到队列中的所有任务被处理,task_done()用于标记任务已完成。正确使用task_done()与put的次数匹配才能避免阻塞。
228

被折叠的 条评论
为什么被折叠?



