Примеры потоков и очереди 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