python多线程队列没有运行或干净地退出
Posted
技术标签:
【中文标题】python多线程队列没有运行或干净地退出【英文标题】:python multithreading queues not running or exiting cleanly 【发布时间】:2016-07-23 19:48:10 【问题描述】:我正在学习 python 多线程和队列。下面创建了一堆线程,它们通过队列将数据传递到另一个线程进行打印:
import time
import threading
import Queue
queue = Queue.Queue()
def add(data):
return ["%sX" % x for x in data]
class PrintThread(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self.queue = queue
def run(self):
data = self.queue.get()
print data
self.queue.task_done()
class MyThread(threading.Thread):
def __init__(self, queue, data):
threading.Thread.__init__(self)
self.queue = queue
self.data = data
def run(self):
self.queue.put(add(self.data))
if __name__ == "__main__":
a = MyThread(queue, ["a","b","c"])
a.start()
b = MyThread(queue, ["d","e","f"])
b.start()
c = MyThread(queue, ["g","h","i"])
c.start()
printme = PrintThread(queue)
printme.start()
queue.join()
但是,我只看到打印出来的第一个线程的数据:
['aX', 'bX', 'cX']
然后没有别的,但程序没有退出。我必须终止进程才能让它退出。
理想情况下,在每个MyThread
进行数据处理并将结果放入队列之后,该线程应该退出吗?同时PrintThread
应该获取队列中的任何内容并打印出来。
在所有MyThread
线程完成并且PrintThread
线程完成处理队列中的所有内容之后,程序应该干净地退出。
我做错了什么?
编辑:
如果每个MyThread
线程都需要一段时间来处理,有没有办法保证PrintThread
线程会等待所有MyThread
线程完成后再退出?
这样打印线程肯定会处理队列中所有可能的数据,因为所有其他线程都已经退出。
例如,
class MyThread(threading.Thread):
def __init__(self, queue, data):
threading.Thread.__init__(self)
self.queue = queue
self.data = data
def run(self):
time.sleep(10)
self.queue.put(add(self.data))
上述修改将等待 10 秒,然后再将任何内容放入队列。打印线程会运行,但我认为它退出太早了,因为队列上还没有数据,所以程序什么也没打印出来。
【问题讨论】:
【参考方案1】:您的PrintThread
不会循环,而是仅打印出单个队列项,然后停止运行。
因此,队列永远不会为空,queue.join()
语句将阻止主程序终止
将PrintThread
的run()
方法更改为以下代码,以便处理所有队列项:
try:
while True:
data = self.queue.get_nowait()
print data
self.queue.task_done()
except queue.Empty:
# All items have been taken off the queue
pass
【讨论】:
你如何解决MyThread
线程都需要5+秒来处理的问题?例如,如果我们在MyThread
中将time.sleep(20)
放在run()
之后,则最终结果为空;什么都没有打印出来。有没有办法保证PrintThread
是最后一个退出的线程?这样可以保证所有数据都在队列中,并且 PrintThread 有机会处理它们,而不管其他线程处理数据所花费的时间。
您需要保持PrintThread
运行,例如通过将其创建为daemon thread。另一种方法是使用threading.Event
来通知线程停止主程序(因为线程本身不知道是否期望队列中有更多项目)。
我设置了printme.setDaemon(True)
,但程序正在打印一些奇怪的输出。例如,我看到像['gX', 'hX'
或['aX', 'bX', 'cX'] ['gX',
这样的损坏列表。这是个问题吗?
在 Python 2 中使用 print
不是线程安全的。请参阅this 和this SO 问题。以上是关于python多线程队列没有运行或干净地退出的主要内容,如果未能解决你的问题,请参考以下文章