Завершение потока Python, ожидающего в очереди или работающего - PullRequest
0 голосов
/ 22 сентября 2019

У меня N рабочих потоков, все они читают из одного queue.SimpleQueue, где основная программа записывает задачи для выполнения.Когда поток получает сообщение из очереди, его задача может длиться несколько минут.Таким образом, если основная программа прерывается (например, CTRL-C или SIGINT), может пройти много времени, прежде чем все потоки завершатся.Однако я бы хотел, чтобы программа завершилась через несколько секунд.Задача, которую поток выполняет , может быть прервана, однако, , что означает, что поток может периодически проверять флаг или переменную события, чтобы определить, должен ли он завершиться.

Так что я придумалСледующее сочетание сторожевых сообщений и переменных событий для достижения цели:

import queue
import threading

# worker thread
def worker_loop(work_queue, thread_id, event):

  while True:
    end = False
    item = work_queue.get()
    # work_queue.task_done()   # not needed for SImpleQueue

    if item is None:
      print("Thread %s: terminating due to sentinel" % thread_id)
      end = True
    else:
      # perform task, periodically checking for event
      for part in range(10):
        print("Thread %s: doing job part %s (item %s)" % (thread_id, part, item))
        do_work(part = part)                # this lasts a few seconds
        result = event.wait(timeout = 0.01)
        if result == True:
          print("Thread %s: terminating due to event" % thread_id)
          end = True
          break

    if end:
      return

# main
WORKERS = 5
THREADS = []

work_queue = queue.SimpleQueue()
event = threading.Event()

for thread_id in range(WORKERS):
  print("[Main] creating thread '%s'" % thread_id)
  t = threading.Thread(target = worker_loop, args = (work_queue, thread_id, event))
  THREADS.append(t)
  t.start()

# main code here...
# ...

# we received a signal, the time has come to terminate all threads...

# kill threads waiting on the queue
for i in range(NUM_THREADS):
  work_queue.put(None)

# signal other threads to terminate ASAP
event.set()

# wait for all threads to terminate
for thread_id in range(NUM_THREADS):
  THREADS[thread_id].join()

sys.exit()

Мой вопрос: безопасен ли этот метод?Мне кажется, что это так, но я решил, что лучше проверить.Есть ли лучшие / более элегантные альтернативы?

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