Код после потоков выполняется рано, почему? - PullRequest
2 голосов
/ 12 июня 2011
from threading import Thread
import time
print 'start of script'

class MyThread(Thread):
    def run(self):
        for i in xrange(10):
            print 'thread->', '['+self.name+']', '('+str(i)+')'
            time.sleep(2)


for i in range(3):
    my_thread = MyThread()
    my_thread.name = i
    my_thread.start()

print 'end of script'

>>> ================================ RESTART ================================
>>> 
start of script
thread->thread->thread->end of script   
[0][1][2]
>>>    (0)(0)(0)


thread->thread->thread->   [0][2][1]   (1)(1)(1)


thread->thread-> thread-> [0] [2] [1] (2) (2)
(2)

thread-> thread->thread->[0]   [2][1](3)  
(3)(3)

thread-> thread->thread->[0]   [2][1](4)  
(4)(4)

thread-> thread->[0]thread->   [2](5)[1] 
 (5)(5)

thread-> [0]thread->thread->   (6)[2][1]
  (6)(6)

thread-> thread->[0]thread->   [2](7)[1] 
 (7)(7)

thread-> thread->[0] thread-> [2] (8) [1]
(8) 
(8)
thread->thread-> thread-> [0] [2] [1] (9) (9)
(9)


>>> 

Как вы видите, я сначала печатаю «начало сценария», затем выполняю несколько потоков, а затем печатаю «конец сценария»

Тем не менее, «конец сценария» печатается сразу после того, как я выполню первый поток, а не после того, как все потоки завершены. Как я могу предотвратить это?

Беспорядочный характер вывода ожидается и фактически желателен, поскольку эти потоки должны выполняться одновременно ...

Я на Windows 7 Python 2.7 кстати ...

Ответы [ 3 ]

7 голосов
/ 12 июня 2011

Это совершенно нормально. Вы не дожидаетесь завершения потоков, поэтому у вашего кода нет причин блокировать после цикла for.

Вам понадобится второй цикл, в котором вы будете вызывать .join() в каждом потоке, если вы хотите их ждать.

Тем не менее, «конец сценария» печатается сразу после того, как я выполню первый поток, а не после того, как все потоки закончили

Это только впечатление, которое вы получаете. Запустите этот код несколько сотен раз, и вы сможете увидеть «конец сценария» перед тем, как какой-либо поток будет выводиться вообще, или после того, как два или три потока будут зарегистрированы. Этот «конец сценария» печатается после запуска всех потоков.

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

Итак, в выводе, который вы опубликовали, первый поток получил немного ресурсов процессора, в то время как основной поток все еще был занят запуском других. Это просто «совпадение».

5 голосов
/ 12 июня 2011

Вы хотите добавить .join(), так как по умолчанию нет оснований для блокировки основной программы до завершения потоков:

my_threads = []
for i in range(3):
    my_thread = MyThread()
    my_thread.name = i
    my_thread.start()
    my_threads.append(my_thread)

for t in my_threads:
    t.join()

print 'end of script'
1 голос
/ 12 июня 2011

Следите за объектами потоков и вызовите join() для объекта, чтобы дождаться завершения потоков перед печатью end of script.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...