Примеры потоков и очереди Python

Я новичок в python (я родом из PHP), я читал учебники и пробовал пару дней, но я не могу понять этот пример очереди (http://docs.python.org/2/library/queue.html)

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() до тех пор, пока элемент не будет доступен, поэтому, если все элементы обработаны и в очереди не осталось, то почему q.get() не блокирует навсегда?

Ответ 1

Потоки в этом коде не выводятся нормально (они действительно заблокированы, когда очередь пуста). Программа не ждет их, потому что они потоки демона.

Программа не выходит сразу и не блокируется навсегда из-за q.join и q.task_done.

Количество незавершенных задач увеличивается, когда элемент добавляется в очередь. Счетчик уменьшается, когда потребительский поток вызывает task_done(), чтобы указать, что элемент был восстановлен, и все работы над ним завершены. Когда количество незавершенных задач падает до нуля, join() разблокируется, и программа существует, не дожидаясь потоков демона.

Ответ 2

У меня была та же проблема. Когда все потоки завершены, я видел "спящие потоки" в списке процессов (используйте top -H -p <pid>, где <pid> - это идентификатор процесса из ps aux | grep python с помощью script).

Я решил эту проблему, заменив "бесконечный цикл" while True на while not q.empty():.

Устранена проблема с "спящими потоками".

def worker():
    while not q.empty():
        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