什么时候需要 Queue.join() ?

SMX*_*SMX 4 python queue multithreading python-3.x

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()
Run Code Online (Sandbox Code Playgroud)

在这个例子中,为什么是q.join()必要的?q.put(None)后续的和操作难道不会t.join()完成同样的事情,即阻塞主线程直到工作线程完成吗?

jar*_*889 5

这是我对这个例子的理解。

每个工作线程无限循环,总是从队列中寻找新的东西。如果它得到的项是None,它会中断并将控制权返回给 main。

因此,首先我们让程序等待队列为空。每次调用都将q.task_done()新项目标记为完成。代码挂在下面,因此我们确保每个项目都标记为完成。

# block until all tasks are done
q.join()
Run Code Online (Sandbox Code Playgroud)

然后,在下面,我们将与工作人员数量相同的None项目添加到队列中(因此我们确保每个工作人员都得到一个。)

for i in range(num_worker_threads):
    q.put(None)
Run Code Online (Sandbox Code Playgroud)

接下来,我们连接所有线程。由于我们None通过队列为每个工人提供了一个项目,因此他们都会损坏。在他们全部打破并恢复控制之前,我们想挂在这里。

for t in threads:
    t.join()
Run Code Online (Sandbox Code Playgroud)

通过这种方式,我们可以确保队列中的每个项目都得到处理,每个工作线程在队列为空时都会中断,并且每个工作线程在我们继续处理代码之前都被关闭,从而有助于避免孤立进程。

  • 是的,我们还在等待,但我认为这是一种编码安全措施。如果在处理队列中的所有项目并且工作人员获得一个项目之前奇迹般地添加了“None”怎么办?我认为这只是一个乏味的编程示例,以确保您了解正在发生的事情,而不必完全理解队列是 FIFO(先进先出)。此外,该示例可以适用于 LIFO(后进先出)实现。但是,对于当前的示例,我相信您可以取出 `q.join()` 就可以了。 (2认同)