【问题标题】:How to start and stop thread?如何启动和停止线程?
【发布时间】:2013-03-31 12:46:06
【问题描述】:

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

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

我的班级:

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

【问题讨论】:

    标签: python multithreading


    【解决方案1】:

    您实际上无法停止然后重新启动线程,因为在其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))
    
    

    【讨论】:

      【解决方案2】:

      这是 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()
      

      【讨论】:

        【解决方案3】:

        stop() 的实现如下所示:

        def stop(self):
            self.stopped = True
        

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

        while conditon:
            inst = Concur()
            inst.start()
        
            #after some operation
            inst.stop()
            #some other operation
        

        Threaddocumentation 清楚地表明 start() 方法只能为类的每个实例调用一次。

        如果您想暂停和恢复线程,则需要使用condition variable

        【讨论】:

        • 它在循环中,我想在代码的开头再次重新启动它。我该怎么做 start-stop-restart-stop-restart ?
        • 他的“主代码”确实会尝试循环重启线程。
        • 对不起,我是这个网站的新手。对不起
        • 将等待和通知方法导致忙等待?
        • 我已经完成了 def wait(self) : self.wait() 和 def notify(self): self.notify()。校准等待然后通知后,发出错误“递归深度太多”
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多