实践:Queue的使用
stevezhou 2014.10.15
被Queue的‘线程安全’这一特性吸引,把一个查排名的小脚本进行了重写。发现用Queue进行线程间数据通信,真心比较好用。
Queue的方法介绍
方法 | 原型 | 说明 |
---|---|---|
Queue | Queue(maxsize=0) | FIFO, maxsize为队列最大长度, <1表示队列长度无限。 |
LifoQueue | LifoQueue(maxsize=0) | LIFO, maxsize为队列最大长度, <1表示队列长度无限。 |
PriorityQueue | PriorityQueue(maxsize=0) | 优先级队列,级别越低越先出来 |
empty | empty() | 队列为空时返回True,否则返回False |
full | full() | 队列满时返回True,否则返回False |
put | put(item,[block[,timeout]]) | 在队尾插入一个项目。put()有两个参数,第一个item为必需的,为插入项目的值;第二个block为可选参数,默认为True,表示当前队列满时,put()方法就使调用线程暂停,直到空出一个数据单元。如果block为False,put方法将引发Full异常 |
get | get(item[,block[,timeout]]) | 从队头删除并返回一个项目。可选参数为block,默认为True。如果队列为空且block为True,get()就使调用线程暂停,直至有项目可用。如果队列为空且block为False,队列将引发Empty异常。 |
qsize | qsize() | 返回队列长度 |
task_done | task_done() | 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号. 注意:在多线程下,注意task_done的位置,每次执行task_done(),unfinished_tasks就减1,应该在一切搞定后,再执行task_done. |
join | join() | 等到队列为空(即队列中所有的项都被取走,处理完毕),再执行别的操作 |
clear | clear() | 清空队列 |
问题:多线程场景中,程序执行完后,不自动退出
方法1:
传入特定值(如None),作为判断结束的标记值 。示例:
def run(self):
while True:
kw=self.queue.get()
if kw==None:
break
#工作代码......
self.queue.task_done() #必须要有
self.queue.task_done() #必须要有
return
注意:这种方法的前提是,你需要先put进一个结束标记项(此例为None)。
方法2:
利用Queue的Empty异常退出循环。示例:
def run(self):
kw=self.queue.get() #因为queue初始为空,所以要将它放在循环外,会产生阻塞,等待队列有可取项为止
with open('rank.txt','a+') as rsfile:
while True:
#工作代码......
try:
kw=self.queue.get(block=False) #设置block=False后,get空队列才会抛出Empty异常
except Queue.Empty:
break
self.queue.task_done() #必须有
self.queue.task_done() #必须有
return
注意:这种方法的局限在于,只能用于队列为空时结束任务的场景。