Как начать и остановить поток?
Извините за старый вопрос. Я уточнил это. Как я могу запустить стоп-поток с моим бедным классом потоков?
EDIT: он находится в цикле, я хочу перезапустить его снова в начале кода. Как я могу запустить start-stop-restart-stop-restart?
Мой класс:
import threading
class Concur(threading.Thread):
def __init__(self):
self.stopped = False
threading.Thread.__init__(self)
def run(self):
i = 0
while not self.stopped:
time.sleep(1)
i = i + 1
В главном коде я хочу:
inst = Concur()
while conditon:
inst.start()
#after some operation
inst.stop()
#some other operation
Ответы
Ответ 1
Это идея Дэвида Хеффернана. Пример ниже выполняется в течение 1 секунды, затем останавливается на 1 секунду, затем выполняется в течение 1 секунды и т.д.
import time
import threading
import datetime as DT
import logging
logger = logging.getLogger(__name__)
def worker(cond):
i = 0
while True:
with cond:
cond.wait()
logger.info(i)
time.sleep(0.01)
i += 1
logging.basicConfig(level=logging.DEBUG,
format='[%(asctime)s %(threadName)s] %(message)s',
datefmt='%H:%M:%S')
cond = threading.Condition()
t = threading.Thread(target=worker, args=(cond, ))
t.daemon = True
t.start()
start = DT.datetime.now()
while True:
now = DT.datetime.now()
if (now-start).total_seconds() > 60: break
if now.second % 2:
with cond:
cond.notify()
Ответ 2
Вы не можете фактически остановить и затем перезапустить поток, так как вы не можете снова вызвать его start()
после завершения его метода run()
. Однако вы можете сделать одно прекращение, а затем возобновить выполнение, используя переменную threading.Condition
чтобы избежать проблем параллелизма при проверке или изменении его рабочего состояния.
Объекты threading.Condition
имеют связанный объект threading.Lock
и методы для ожидания его освобождения и уведомят все ожидающие потоки, когда это произойдет. Вот пример, полученный из кода в вашем вопросе, который показывает, как это делается. В примере кода я сделал переменную Condition
частью экземпляров подкласса Thread
чтобы лучше инкапсулировать реализацию и избежать необходимости вводить дополнительные глобальные переменные:
from __future__ import print_function
import threading
import time
class Concur(threading.Thread):
def __init__(self):
super(Concur, self).__init__()
self.iterations = 0
self.daemon = True # Allow main to exit even if still running.
self.paused = True # Start out paused.
self.state = threading.Condition()
def run(self):
self.resume()
while True:
with self.state:
if self.paused:
self.state.wait() # Block execution until notified.
# Do stuff.
time.sleep(.1)
self.iterations += 1
def resume(self):
with self.state:
self.paused = False
self.state.notify() # Unblock self if waiting.
def pause(self):
with self.state:
self.paused = True # Block self.
class Stopwatch(object):
""" Simple class to measure elapsed times. """
def start(self):
""" Establish reference point for elapsed time measurements. """
self.start_time = time.time()
return self.start_time
@property
def elapsed_time(self):
""" Seconds since started. """
try:
start_time = self.start_time
except AttributeError: # Wasn't explicitly started.
start_time = self.start()
return time.time() - start_time
MAX_RUN_TIME = 5 # Seconds.
concur = Concur()
stopwatch = Stopwatch()
print('Running for {} seconds...'.format(MAX_RUN_TIME))
concur.start()
while stopwatch.elapsed_time < MAX_RUN_TIME:
concur.resume()
# ... do some concurrent operations.
concur.pause()
# Do some other stuff...
# Show Concur thread executed.
print('concur.iterations: {}'.format(concur.iterations))
Ответ 3
Реализация stop()
будет выглядеть так:
def stop(self):
self.stopped = True
Если вы хотите перезапустить, тогда вы можете просто создать новый экземпляр и запустить его.
while conditon:
inst = Concur()
inst.start()
#after some operation
inst.stop()
#some other operation
documentation для Thread
дает понять, что метод start()
может быть вызван только один раз для каждого экземпляра класса.
Если вы хотите приостановить и возобновить поток, вам нужно будет использовать переменную условия .