Почему поток python.Thread имеет начало, а не остановку?
Поток модуля Python имеет объект Thread
использоваться для запуска процессов и функций в другом потоке. Этот объект имеет start
метод, но нет stop
метод. В чем причина Thread
не может быть остановлено мое призвание простого stop
метод? Я могу представить себе случаи, когда неудобно использовать join
метод...
5 ответов
start
может быть универсальным и иметь смысл, потому что он просто запускает цель потока, но что бы универсальный stop
делать? В зависимости от того, что делает ваш поток, вам может потребоваться закрыть сетевые подключения, освободить системные ресурсы, файл дампа и другие потоки или любое количество других нестандартных нетривиальных задач. Любая система, которая могла бы выполнять даже большинство из этих вещей в общем виде, добавляла бы так много накладных расходов каждому потоку, что это не стоило бы того, и была бы настолько сложной и изрезанной в особых случаях, что было бы почти невозможно работать с. Вы можете отслеживать все созданные темы без join
добавив их в ваш основной поток, затем проверьте их состояние выполнения и передайте им какое-нибудь сообщение о завершении, когда основной поток отключится.
Определенно возможно реализовать Thread.stop
метод, как показано в следующем примере кода:
import threading
import sys
class StopThread(StopIteration): pass
threading.SystemExit = SystemExit, StopThread
class Thread2(threading.Thread):
def stop(self):
self.__stop = True
def _bootstrap(self):
if threading._trace_hook is not None:
raise ValueError('Cannot run thread with tracing!')
self.__stop = False
sys.settrace(self.__trace)
super()._bootstrap()
def __trace(self, frame, event, arg):
if self.__stop:
raise StopThread()
return self.__trace
class Thread3(threading.Thread):
def _bootstrap(self, stop_thread=False):
def stop():
nonlocal stop_thread
stop_thread = True
self.stop = stop
def tracer(*_):
if stop_thread:
raise StopThread()
return tracer
sys.settrace(tracer)
super()._bootstrap()
################################################################################
import time
def main():
test = Thread2(target=printer)
test.start()
time.sleep(1)
test.stop()
test.join()
def printer():
while True:
print(time.time() % 1)
time.sleep(0.1)
if __name__ == '__main__':
main()
Thread3
Похоже, что класс выполняет код примерно на 33% быстрее, чем Thread2
учебный класс.
Убивать нитки надежным способом не очень легко. Подумайте о необходимых очистках: какие блокировки (которые могут совместно использоваться другими потоками!) Должны автоматически сниматься? В противном случае вы легко попадете в тупик!
Лучше всего сделать правильное отключение самостоятельно, а затем установить
mythread.shutdown = True
mythread.join()
чтобы остановить поток.
Конечно, ваша тема должна сделать что-то вроде
while not this.shutdown:
continueDoingSomething()
releaseThreadSpecificLocksAndResources()
часто проверять флаг отключения. В качестве альтернативы вы можете полагаться на специфические для ОС механизмы сигнализации для прерывания потока, перехвата прерывания и последующей очистки.
Очистка - самая важная часть!
Остановка потока должна быть осуществлена программистом. Например, если вы спроектировали ваш поток, чтобы проверить его, есть какие-либо запросы на немедленное прекращение его работы. Если python (или любой другой язык потоков) позволяет вам просто остановить поток, то у вас будет код, который только что остановился. Это подвержено ошибкам и т. Д.
Представьте, что ваш поток записывает вывод в файл, когда вы его убили / остановили. Тогда файл может быть незаконченным и поврежденным. Однако, если вы просто дали сигнал потоку, который хотите остановить, он мог бы закрыть файл, удалить его и т. Д. Вы, программист, решили, как с этим обращаться. Python не может угадать для вас.
Я бы предложил почитать теорию многопоточности. Достойное начало: http://en.wikipedia.org/wiki/Multithreading_(software)
На некоторых платформах вы не можете принудительно "остановить" поток. Это также плохо, поскольку поток не сможет очистить выделенные ресурсы. И это может произойти, когда поток выполняет что-то важное, например, ввод-вывод.