什么时候Queue.join()是必要的?

时间:2017-02-22 20:00:37

标签: python multithreading python-3.x queue

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()操作是否完成了阻塞主线程的相同操作,直到工作线程完成为止?

1 个答案:

答案 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()

这样做,我们确保处理队列中的每个项目,每个工作人员在队列为空时中断,并且每个工作人员在我们继续使用我们的代码之前关闭,这有助于避免孤儿进程。