写一个扫描器用到了python多线程和消息队列的东西,直接用queue却没达到预期效果,网上找了一下资料,发现解释的没那么明白。

看了一下官方文档。
链接地址:https://docs.python.org/2/library/queue.html?highlight=task_done#Queue.Queue.task_done
文档写的也有点模糊。
Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
Queue.join() 实际上意味着等到队列为空,再执行别的操作

个人理解

当线程通过队列取值一次后,也就是queue.get(),队列会记录这个取值的记录。但是此时队列的数量已经减少1了。
如果没有使用队列执行task_done()这个方法。则队列就会认为这个任务还在执行中。
可以理解为队列为这个任务是否完成单独设置了个计数器。
总结一下就是:
如果线程里每从队列里取一次,但没有执行task_done(),则join无法判断队列到底有没有结束,在最后执行个join()是等不到结果的,会一直挂起。

示例代码:
会在join()的地方无限挂起,因为join在等队列清空,但是由于没有task_done,它认为队列还没有清空,还在一直等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# -*- coding:utf-8 -*-
import threading
import Queue
from time import sleep

que = Queue.Queue()

class Testthread(threading.Thread):
def __init__(self,que):
threading.Thread.__init__(self)
self.queue = que
def run(self):
while True:
sleep(0.1)
item = self.queue.get()
print(item)
self.queue.task_done()
tasks = [Testthread(que) for x in range(2)]

for x in tasks:
t = Testthread(que)
t.setDaemon(True)
t.start()

for x in range(10):
que.put(x)
que.join()

print('all done')

如果把

1
self.queue.task_done()

注释去掉,就可以正常运行了。