Как правильно закрыть поток в python?

Как правильно закрыть поток? Возможно ли это в python? Что делает thread.exit()? Жив ли поток после thread.exit()?
  • Вопрос задан
  • 6071 просмотр
Пригласить эксперта
Ответы на вопрос 1
Sly_tom_cat
@Sly_tom_cat
.
А не надо извне закрывать потоки и процессы. Можно получить кучу неприятностей.
В нормально проработанном решении потоки/процессы сами должны закрываться тогда, когда нужно. Если нужно управлять этим извне - то для этого и существуют примитивы типа семафоров/флагов/эвентов.

В потоки полезно засовывать поиск всякий или подготовку кусочков общего решения. При этом можно использовать два шаблонных примитива: "коллектор" и "победитель":

"Коллектор":
import threading
def job(id, ...):
global res
  <Подготовка блока данных>
  res[id] = <блок подготовленных данных>
  return

res = []
for i in range(N):   # запуск N потоков
    res.append(<пустой блок>)
    threading.Thread(target=job, args=(i, ...)).start()
for th in threading.enumerate():  # ожидание всех потоков 
    if th != threading.currentThread():
      th.join()
<здесь массив с блоками полностью собран >


"Победитель":
import threading
def job(...):
  global val
  global event
  while <не нашли>
    <элементарный шаг поиска>
    if event.is_set():
      return   # кто-то уже нашел искомое
  val=<то что нашли>
  event.set()   # этот поток нашел искомое и радостно сообщает всем об этом
  return

val = None  # искомое значение
event = threading.Event() # флаг сигнализирующий о том что решение найдено
threads = []
for i in range(N):
    threads.append(threading.Thread(target=job, args=(i, ...)))
    threads[-1].start()
event.wait()  # тут основной поток ждет сигнала о победе от одного из запущенных потоков
# если есть шанс, что победителя может и не быть, то в wait() нужно указать таймаут
# и читать значение event.wait(), что бы узнать - сработал таймаут или появился победитель.
<тут обрабатываем найденное>
for th in threads:   # Подчищаем за собой - гарантированно собираем закрывшиеся потоки
      th.join()


ЗЫ последний цикл в "победителе" - часто не обязателен, но если сама эта процедура запущена во множестве потоков, то можно получить так называемый "потоковый потоп", когда потоки не успевают закрываться сами и плодятся в системе со страшной силой, с предсказуемыми последствиями.
ЗЫЫ также обратите внимание на варианты работы с набором потоков. В примере "Коллектор" не подразумевается, что в программе есть какие-то еще потоки, поэтому сборка потоков идет всех, кроме текущего (основного потока программы). А вот в "Победитель" потоки сохраняются в списке и из этого списка потом собираются. Это позволяет иметь в программе и другие потоки работающие в параллель с нашим поиском победителя (и в частности запускать сам такой поиск победителя в независимых потоках). Правда для оформления этого кода в отдельные потоки - возможно потребуется избавиться от глобальных переменных и работать только через передаваемые в job параметры.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы