1

这里的官方文档给出了以下示例:

def worker():
    while True:
        item = q.get()
        do_work(item)
        q.task_done()

q = Queue()
for i in range(num_worker_threads):
    t = Thread(target=worker)
    t.daemon = True
    t.start()

for item in source():
    q.put(item)

q.join()       # block until all tasks are done

我想确保在我的主线程继续之前,此时所有线程都被杀死。我想在队列中的所有任务都被处理之后, q.get() 方法会引发一个异常,这应该会杀死线程。那是对的吗?

4

2 回答 2

2

否。如果队列中没有项目,get默认情况下会等待项目被放入队列。如果您希望它在没有更多项目时引发异常,请传递它block=False或使用get_nowait.

一旦你使用了 non-blocking get,它应该都可以工作,但是你的线程因为在正常情况下引发的异常而死是相当不雅的。我建议用一个try块包围它,如果由于队列为空而引发异常,请干净地停止线程:

try:
    item = q.get(block=False)
except queue.Empty:
    return
于 2013-02-10T02:41:27.057 回答
0

如果任何do_work()'s 调用引发异常,则运行它的线程将退出。您的主线程将永远阻塞q.join() 因为在这种情况下q.get()没有被跟随。q.task_done()

您可以使用线程池重写示例:

from multiprocessing.dummy import Pool # use threads

p = Pool(num_worker_threads)    
for _ in p.imap_unordered(do_work, source()):
    pass
p.close()
p.join() # no threads after this point

在这种情况下,如果do_work()引发异常;它被传播到主线程并退出(池线程是守护进程,因此它们不会保持程序运行)。

基于 - 的解决方案的另一种替代Queue方法是将标记值放入队列(每个线程一个值)并worker()在遇到标记时退出,例如

STOP = object()

def worker(queue):
    for item in iter(queue.get, STOP): # until STOP is encountered
        do_work(item)

# instead of `q.join()`
for _ in threads: q.put(STOP)
for t in threads: t.join() # no threads after this point
于 2013-05-10T09:02:21.523 回答