Почему поток 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)

На некоторых платформах вы не можете принудительно "остановить" поток. Это также плохо, поскольку поток не сможет очистить выделенные ресурсы. И это может произойти, когда поток выполняет что-то важное, например, ввод-вывод.

Другие вопросы по тегам