如何启动和停止一个线程

12

如何使用我的简陋线程类启动和停止线程?

它处于循环状态,我想在代码开头重新启动它。如何实现启动-停止-重新启动-停止-重新启动?

我的类:

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
3个回答

22
你实际上不能停止并重新启动一个线程,因为在它的run()方法终止后,你不能再次调用其start()方法。但是,你可以使用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 pause(self):
        with self.state:
            self.paused = True  # Block self.

    def resume(self):
        with self.state:
            self.paused = False
            self.state.notify()  # Unblock self if waiting.


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

    @property
    def elapsed_time(self):
        """ Seconds since started. """
        try:
            return time.time() - self.start_time
        except AttributeError:  # Wasn't explicitly started.
            self.start_time = time.time()
            return 0



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()
    # Can also do other concurrent operations here...
    concur.pause()
    # Do some other stuff...

# Show Concur thread executed.
print('concur.iterations: {}'.format(concur.iterations))


7
这是David Heffernan的想法具体化。以下示例运行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()

5
stop()的实现应该如下所示:
def stop(self):
    self.stopped = True

如果你想重新启动,只需创建一个新实例并开始运行即可。

while conditon:
    inst = Concur()
    inst.start()

    #after some operation
    inst.stop()
    #some other operation

对于Thread文档明确指出,start()方法每个实例只能调用一次。

如果您想要暂停和恢复一个线程,则需要使用条件变量


它在循环中,我想要重新开始,在代码的开头。我该如何做到启动-停止-重新启动-停止-重新启动? - user2229183
他的“主代码”试图在循环中重新启动线程。 - user4815162342
wait() 和 notify() 方法会导致忙等吗? - user2229183
我已经编写了def wait(self) : self.wait()和def notify(self): self.notify()。在调用wait然后notify之后,会发出错误提示“递归深度太大”。 - user2229183
你需要使用条件变量,这样你就可以进行非忙等待。 - David Heffernan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接