0

我在 python 中编写了一个生产者线程,我想在设置某个事件时停止它的执行。我不知道如何使用threading.Event这个目的。所以,我自己写了一些代码:-

我使用了一个self.shouldStop默认设置为 False 的变量。每当我希望停止生产者线程的执行时,我设置p.shouldStop为 True

import Queue
import threading
import time

class ProducerThread( threading.Thread ):
    def __init__( self, q ):
        super( ProducerThread, self ).__init__()

        self._q = q
        self.shouldStop = False
    def run( self ):
        for i in range( 5 ):
            if self.shouldStop is True:
                return
            self._q.put( i )

class ConsumerThread( threading.Thread ):
    def __init__( self, q ):
        super( ConsumerThread, self ).__init__()
        self._q = q

    def run( self ):
        while True:
            data = self._q.get()
            if data == 'Stop':
                print 'returning from the thread as I got %s message' % data
                return
            print "%s got %s. Sleeping for %s seconds. %s" % ( self.getName(), data, data, time.time() )
            time.sleep( data )
            print "%s woke up from sleep after %s seconds %s" % ( self.getName(), data, time.time() )
    def stop( self ):
        self._q.put( "Stop" )
if __name__ == '__main__':
    q = Queue.Queue( 1 )
    p = ProducerThread( q )
    t = ConsumerThread( q )
    p.start()
    t.start()
    p.shouldStop = True
    p.join()
    t.stop()
    t.join()

我的问题是:

有没有更好的方法通过删除使用shouldStop和使用来实现这一点threading.Event

4

1 回答 1

1

您必须在所有线程之间共享相同的事件对象(就像您已经对队列所做的那样)。

然后用于is_set()检查是否设置了事件。您还可以使用wait()(with a timeout) 并捕获超时错误来确定事件是否已设置。我发现解决方案is_set()更容易阅读,所以这就是下面发布的内容:

import Queue
import threading
import time

class ProducerThread(threading.Thread):

    def __init__(self, work_queue, shutdown_event):
        super(ProducerThread, self).__init__()

        self._work_queue     = work_queue
        self._shutdown_event = shutdown_event

    def run(self):
        for i in range(5):
            if self._shutdown_event.is_set():
                return
            else:
                self._work_queue.put(i)

class ConsumerThread(threading.Thread):

    def __init__(self, work_queue, shutdown_event):
        super(ConsumerThread, self).__init__()
        self._work_queue     = work_queue
        self._shutdown_event = shutdown_event

    def run(self):
        while True:
            try:
                data = self._work_queue.get(timeout=1)
            except Queue.Empty:
                if self._shutdown_event.is_set():
                    print 'returning from thread; queue is empty and ' \
                          'shutdown_event.is_set() is True'
                    return
                else:
                    continue
            if self._shutdown_event.is_set():
                print 'returning from thread; shutdown_event.is_set() is True'
                return
            else:
                print "%s got %s. Sleeping for %s seconds. %s" % (
                    self.getName(), data, data, time.time())
                time.sleep(1.0+data/10)
                print "%s woke up from sleep after %s seconds %s" % (
                    self.getName(), str(1.0+data/10), time.time())


if __name__ == '__main__':
    work_queue = Queue.Queue(maxsize = 1)
    shutdown_event = threading.Event()
    producer = ProducerThread(work_queue, shutdown_event)
    consumer = ConsumerThread(work_queue, shutdown_event)
    producer.start()
    consumer.start()
    p
    time.sleep(10)
    print 'MainThread: calling shutdown_event.set()'
    shutdown_event.set()
    producer.join()
    consumer.join()
于 2013-04-17T08:40:18.190 回答