Python 如何启动和停止线程?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15729498/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 20:49:15  来源:igfitidea点击:

How to start and stop thread?

pythonmultithreading

提问by user2229183

Sorry for the old question. I have clarified it. How can I start an stop thread with my poor thread class?

对不起,老问题。我已经澄清了。如何使用我糟糕的线程类启动停止线程?

EDIT: It is in loop, I want to restart it again at the beginning of the code. How can I do start-stop-restart-stop-restart?

编辑:它在循环中,我想在代码的开头再次重新启动它。我该如何开始-停止-重启-停止-重启?

My class:

我的课:

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

In the main code, I want:

在主代码中,我想要:

inst = Concur()

while conditon:
    inst.start()

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

采纳答案by unutbu

This is David Heffernan's idea fleshed-out. The example below runs for 1 second, then stops for 1 second, then runs for 1 second, and so on.

这是大卫赫弗南的想法充实。下面的示例运行 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()

回答by David Heffernan

The implementation of stop()would look like this:

的实现stop()如下所示:

def stop(self):
    self.stopped = True

If you want to restart, then you can just create a new instance and start that.

如果您想重新启动,那么您可以创建一个新实例并启动它。

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

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

The documentationfor Threadmakes it clear that the start()method can only be called once for each instance of the class.

文档Thread清楚地表明,该start()方法只能被调用一次为类的每个实例。

If you want to pause and resume a thread, then you'll need to use a condition variable.

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

回答by martineau

You can't actually stop and then restart a thread since you can't call its start()method again after its run()method has terminated. However you can make one cease and then later resume execution by using a threading.Conditionvariable to avoid concurrency problems when checking or changing its running state.

您实际上无法停止然后重新启动线程,因为start()在其run()方法终止后您无法再次调用其方法。但是,您可以通过使用threading.Condition变量来停止执行,然后在稍后恢复执行,以避免在检查或更改其运行状态时出现并发问题。

threading.Conditionobjects have an associated threading.Lockobject and methods to wait for it to be released and will notify any waiting threads when that occurs. Here's an example derived from the code in your question which shows this being done. In the example code I've made the Conditionvariable a part of Threadsubclass instances to better encapsulate the implementation and avoid needing to introduce additional global variables:

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))