在调用函数时,结束这个线程的最佳方法是什么?
我在处理这个队列时遇到了一些麻烦:
import Queue
import threading
class test(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.request_queue = Queue.Queue()
def addtoqueue(self, item):
self.request_queue.put(item)
def run(self):
while True:
item = self.request_queue.get(True)
print item
这个简单的类实现了一个线程队列。调用 test::addtoqueue
方法会把一个项目添加到队列中。线程会等待队列中有新项目被添加,然后立即打印出来,并继续等待下一个项目。
我遇到的问题是应用程序关闭时,怎么才能优雅地结束这个线程?我可以使用条件变量,但我该如何同时等待条件变量的通知和队列中新项目的到来呢?
3 个回答
1
我建议你修改一下你的while循环的条件,让它检查一个本地变量。同时,添加一个“杀死开关”,这样外部程序就可以关闭这个线程。你可能还需要扩展一下kill_me
,以便优雅地处理对象和它的队列(比如,如果你想在下次运行时保存这个队列)。
编辑 我还在里面添加了一个has_finished
变量,这样kill_me
就可以阻止主进程线程。这应该能让线程在返回主流程之前先退出。
我可能把事情搞得有点复杂了;)
class test(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.request_queue = Queue.Queue()
self.is_running = True
self.has_finished = False
def addtoqueue(self, item):
self.request_queue.put(item)
def kill_me(self):
self.is_running = False
while not self.has_finished:
pass
def run(self):
while self.is_running:
item = self.request_queue.get(True)
print item
self.has_finished = True
1
做最简单的事情,看看能不能成功——在这个情况下,可能就是使用一个哨兵(Sentinel)。虽然 threading
是受到 Java 线程库的启发,但在 Python 中,最简单的方法并不是像 Java 那样去继承 threading.Thread
,而是直接把一个函数和它的参数传给 threading.Thread()
:
DONE = object() # Sentinel
def run(queue):
while True:
item = queue.get()
queue.task_done()
if item is DONE:
break
print item
request_queue = Queue.Queue()
some_thread = Thread(target=run, args=(request_queue,))
some_thread.start()
request_queue.put('hey')
request_queue.put('joe')
request_queue.put(DONE)
1
你可以给线程发送一些“毒药”来结束它:
poison = None # something you wouldn't normally put in the Queue
class test(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.request_queue = Queue.Queue()
def kill(self):
self.addtoqueue(poison)
def addtoqueue(self, item):
self.request_queue.put(item)
def run(self):
while True:
item = self.request_queue.get(True)
if item is poison:
# do stuff
return # end thread
print item