Уведомления

Группа в Telegram: @pythonsu

#1 Янв. 11, 2012 21:49:15

Ed
От:
Зарегистрирован: 2008-12-13
Сообщения: 1032
Репутация: +  13  -
Профиль   Отправить e-mail  

Помогите понять многопоточность.

Чем мой не угодил? Давайте разбираться. Попытайтесь понять как работает мой код, задавайте вопросы. Когда поймете - модифицируйте ту часть, которая собственно делает работу, чтобы она делала то, что вам нужно. Вот такой план. Вуаля.



Офлайн

#2 Янв. 12, 2012 04:24:50

Soteric
От:
Зарегистрирован: 2010-09-19
Сообщения: 352
Репутация: +  20  -
Профиль   Отправить e-mail  

Помогите понять многопоточность.

Ваши потоки работают в бесконечном цикле и не знают когда им завершить работу. Когда очередь пустеет, то они “повисают” здесь

host = self.queue.get()
в ожидании новых задач. Вы можете в конце класть в очередь некие объекты-маркеры, получение которых будет для потока сигналом к остановке.
# Класс объекта-маркера
class JobDone(object):
pass
...
# После того как в очередь положили все host, создаем
# и кладем число объектов-маркеров по числу потоков
for i in range(60):
queue.put(JobDone())
...
# В коде потока проверяем что мы достали из очереди и если
# это объект-маркер завершения работы, то выходим из цикла
while True:
#grabs host from queue
host = self.queue.get()

if isinstance(host, JobDone):
break
ДОБАВЛЕНО: И забыл еще сказать, что выполнение задачи должно быть обернуто в try-finally. Поскольку если ваш поток совершит ошибку, то он завершится не отчитавшись о выполнении задачи. Это значит, что если в вашем коде вы сделаете queue.join(), которое приостановит выполнение основного потока до выполнения всех задач, то никогда не сможете выйти из этого ожидания. Поскольку поток задачу на обработку взял, но queue.task_done() так и не выполнил.
while True:
try:
#grabs host from queue
host = self.queue.get()

if isinstance(host, JobDone):
break
...
except Exception as e:
# При желании записываем сведения об ошибке в лог
finally:
queue.task_done()



Отредактировано (Янв. 12, 2012 09:06:54)

Офлайн

#3 Янв. 12, 2012 09:04:11

vlados
От:
Зарегистрирован: 2011-07-28
Сообщения: 64
Репутация: +  0  -
Профиль   Отправить e-mail  

Помогите понять многопоточность.

Спасибо всем за ответы, но ошибка была куда проще, чем вы думали. Ошибка заключается в том, что я поставил неправильную структуру.
Эд, мне было трудно понять ваш код, было много неясностей, я хотел у вас спросить о них, но потом я нашел сайт где нашел этот пример и хорошее описание.
Было так:

def main():

#spawn a pool of threads, and pass them queue instance
for i in range(60):
t = ThreadUrl(queue)
t.setDaemon(True)
t.start()

#populate queue with data
for host in hosts:
queue.put(host)

#wait on the queue until everything has been processed
queue.join()
А надо так:
def main():

#spawn a pool of threads, and pass them queue instance
for i in range(60):
t = ThreadUrl(queue)
t.setDaemon(True)
t.start()

#populate queue with data
for host in hosts:
queue.put(host)

#wait on the queue until everything has been processed
queue.join()



Офлайн

#4 Янв. 12, 2012 11:10:17

Soteric
От:
Зарегистрирован: 2010-09-19
Сообщения: 352
Репутация: +  20  -
Профиль   Отправить e-mail  

Помогите понять многопоточность.

Да, пардон. Не обратил внимания, что это демонические потоки, которые бесконечно работать не будут :)



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version