Завершение программы с дочерними потоками выполнения

zavershenie programmy s dochernimi potokami vypolneniya Системные инструменты параллельного выполнения

Обратите также внимание, что сценарий завершает свою работу вместе с завершением главного потока, при том, что потоки-потребители продолжают выполнять свой бесконечный цикл. Этот прием прекрасно действует в Windows (и в большинстве других систем) — при использовании модуля _thread программа просто завершает свою работу вместе с главным потоком. Именно поэтому мы использовали функцию sleep в некоторых примерах — чтобы дать дочерним потокам возможность завершить свою работу, и именно поэтому нам нет необходимости беспокоиться о завершении потоков-потребителей, которые в данном примере выполняются в бесконечном цикле.

Однако при использовании альтернативного модуля threading программа не может завершиться, когда хотя бы один поток продолжает работу, если только он не был запущен, как поток-демон. В частности, программа завершается, когда в ней остаются только потоки-демоны. При создании потоки наследуют признак принадлежности к потокам- демонам от потока, породившего их. Главный поток в программах на языке Python не может быть демоном, тогда как потоки, созданные без помощи этого модуля, считаются демонами (включая некоторые потоки, создаваемые расширениями на языке C). Чтобы переопределить признак, унаследованный по умолчанию, можно вручную установить атрибут daemon объекта потока. Другими словами, потоки, не относящиеся к потокам-демонам, препятствуют завершению программы, и программы продолжают работать, пока не завершатся все потоки, созданные под управлением модуля threading.

Эту особенность можно рассматривать как достоинство или как недостаток, в зависимости от потребностей программы, — с одной стороны, когда не используется метод join, или когда главный поток не приостанавливается на некоторое время, она может принудительно завершать рабочие потоки; с другой стороны, она может препятствовать завершению программы, как показано в примере 5.14. Чтобы этот пример мог работать при использовании модуля threading, используйте следующее альтернативное решение (смотрите полную версию в файле queuetest3. py в дереве примеров, а также сценарий threadcountthreading.py — в качестве демонстрации того, где может пригодиться препятствование завершению):

import threading, queue, time

def producer(idnum, dataqueue):

def consumer(idnum, dataqueue):

if __name__ == ‘__main__’:

for i in range(numconsumers):

thread = threading.Thread(target=consumer, args=(i, dataQueue)) thread.daemon = True # иначе программа не завершится!

thread.start()

waitfor = []

for i in range(numproducers):

thread = threading.Thread(target=producer, args=(i, dataQueue)) waitfor.append(thread) thread.start()

for thread in waitfor: thread.join() # или большое значение в time.sleep() print(‘Main thread exit.’)

Мы еще вернемся к потокам-демонам и к проблеме завершения потоков в главе 10, когда будем изучать особенности реализации графических интерфейсов. Как мы увидим, в том контексте все происходит точно так же, за исключением того, что там главный поток обычно занимается обслуживанием графического интерфейса.

Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011

Каталог сайтов Всего.ру
Оцените статью
Секреты программирования
Добавить комментарий