有人可以详细说明为什么这个线程代码可以调用一个类'方法永远不会完成?
from Queue import Queue
from threading import Thread
class SimpleThing(object):
def __init__(self, name):
self.name = name
def print_name(self):
print self.name
class ThingSpawner(object):
def __init__(self, name_list):
self.things = [SimpleThing(name) for name in name_list]
self.thread_queue = Queue()
def run(self):
for thing in self.things:
t = Thread(target=thing.print_name, name=thing.name)
t.daemon = True
t.start()
self.thread_queue.put(t)
self.thread_queue.join()
thing_list = ['cat', 'dog', 'llama', 'bat']
sp = ThingSpawner(thing_list)
sp.run()
代码将清楚地运行print_name
方法,但不会join()
并退出。
此外,修改此代码以使join()
完成的最佳方法是什么?其动机是将一个现有的python控件类用于一些硬件,并允许您并行调用控件类的(非常慢)方法。谢谢!
答案 0 :(得分:1)
当你做的时候
self.thread_queue.put(t)
显然,您正在为Queue
添加一些线程。但是,我不确定为什么。你永远不会再使用那个队列来做任何事情,而且完全没必要。更糟糕的是,你打电话给
self.thread_queue.join()
这基本上等待队列清空,永远不会发生,因为你永远不会清空它或对它做任何事情。
如果我复制粘贴所有代码,但根本没有任何Queue
,那么一切都很好......
from threading import Thread
class SimpleThing(object):
def __init__(self, name):
self.name = name
def print_name(self):
print self.name
class ThingSpawner(object):
def __init__(self, name_list):
self.things = [SimpleThing(name) for name in name_list]
def run(self):
for thing in self.things:
t = Thread(target=thing.print_name, name=thing.name)
t.daemon = True
t.start()
thing_list = ['cat', 'dog', 'llama', 'bat']
sp = ThingSpawner(thing_list)
sp.run()
然而,这不是你想要的!因为你的线程是守护进程,所以当主程序退出时它们将退出,即使它们尚未完成(如果我在打印名称之前添加了sleep(1)
之类的延迟)。如果要等待它们完成,您应该在线程上调用join()
,而不是队列。所以我们首先返回线程:
def run(self):
all_threads = []
for thing in self.things:
t = Thread(target=thing.print_name, name=thing.name)
t.daemon = True
t.start()
all_threads.append(t)
return all_threads
当我们run
时,我们会这样做:
threads = sp.run()
for t in threads:
t.join()
答案 1 :(得分:0)
感谢Ofer提供了我刚才接受的明确答案 - 我确实没有正确使用队列!现在你已经重新认识了队列,你已经指出了我的错误,为了繁荣,这是使用队列的另一种方法:
from Queue import Queue
from threading import Thread
class SimpleThing(object):
def __init__(self, name, q):
self.name = name
def print_name(self, q):
print self.name
q.get()
q.task_done()
class ThingSpawner(object):
def __init__(self, name_list):
self.thread_queue = Queue()
self.things = [SimpleThing(name, self.thread_queue) for name in name_list]
def run(self):
for thing in self.things:
t = Thread(target=thing.print_name, name=thing.name, args=(self.thread_queue,))
t.daemon = True
t.start()
self.thread_queue.put(t)
self.thread_queue.join()
thing_list = ['cat', 'dog', 'llama', 'bat']
sp = ThingSpawner(thing_list)
sp.run()
一旦我理解了我的错误,This tutorial对线程和队列很有用。