Python 3文档给出了一个使用队列(https://docs.python.org/3/library/queue.html)的工作线程的示例:
def worker():
while True:
item = q.get()
if item is None:
break
do_work(item)
q.task_done()
q = queue.Queue()
threads = []
for i in range(num_worker_threads):
t = threading.Thread(target=worker)
t.start()
threads.append(t)
for item in source():
q.put(item)
# block until all tasks are done
q.join()
# stop workers
for i in range(num_worker_threads):
q.put(None)
for t in threads:
t.join()
在这个例子中,为什么q.join()
是必要的?后续的q.put(None)
和t.join()
操作是否完成了阻塞主线程的相同操作,直到工作线程完成为止?
答案 0 :(得分:1)
以下是我对这个例子的理解。
每个工作人员无限循环,总是从队列中寻找新的东西。如果它获得的项目是None
,它会中断并将控制权返回给main。
所以,首先我们让程序等待队列为空。每次调用q.task_done()
都会将新项目标记为已完成。代码挂起以下内容,因此我们确保每个项目都标记为已完成。
# block until all tasks are done
q.join()
然后,在下面,我们将相同数量的None
项添加到队列中,因为有工人(因此我们确保每个工作人员获得一个。)
for i in range(num_worker_threads):
q.put(None)
接下来,我们加入所有主题。由于我们通过队列给每个工人一个None
项目,所以他们都会破坏。在它们全部破裂并返回控制之前,我们想要挂在这里。
for t in threads:
t.join()
这样做,我们确保处理队列中的每个项目,每个工作人员在队列为空时中断,并且每个工作人员在我们继续使用我们的代码之前关闭,这有助于避免孤儿进程。