需要一些关于Python线程/队列的帮助
import threading
import Queue
import urllib2
import time
class ThreadURL(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self.queue = queue
def run(self):
while True:
host = self.queue.get()
sock = urllib2.urlopen(host)
data = sock.read()
self.queue.task_done()
hosts = ['http://www.google.com', 'http://www.yahoo.com', 'http://www.facebook.com', 'http://stackoverflow.com']
start = time.time()
def main():
queue = Queue.Queue()
for i in range(len(hosts)):
t = ThreadURL(queue)
t.start()
for host in hosts:
queue.put(host)
queue.join()
if __name__ == '__main__':
main()
print 'Elapsed time: {0}'.format(time.time() - start)
我一直在努力理解如何进行线程处理,经过几个教程后,我得出了上面的代码。
这段代码应该完成以下几件事:
- 初始化队列
- 创建线程池,然后将主机列表放入队列
- 我的ThreadURL类应该在有主机进入队列后开始工作,并读取网站数据
- 程序应该结束
我首先想知道的是,我这样做对吗?这是处理线程的最佳方法吗?
其次,我的程序无法正常退出。它打印出Elapsed time
这一行后就卡住了。我必须强制关闭终端才能让它消失。我猜这可能是因为我错误使用了queue.join()
?
3 个回答
2
有一点要注意,在线程运行的函数里,有一个一直循环的部分(while True),如果发生了某些错误,可能会导致task_done()这个函数没有被调用,而get()这个函数已经被调用了。这样的话,queue.join()就可能永远不会结束。
2
看起来没问题。yann说的关于守护进程的建议是对的,这样可以解决你程序卡住的问题。我唯一想问的是,为什么要使用队列呢?你并没有进行跨线程的通信,所以似乎可以直接把主机信息作为参数传给ThreadURL的初始化方法,这样就可以省去队列了。
这没什么错,只是好奇而已。
8
你的代码看起来不错,而且很整洁。
你的应用程序之所以还“卡住”,是因为工作线程还在运行,它们在等主程序往队列里放东西,即使你的主线程已经结束了。
解决这个问题最简单的方法是把这些线程标记为守护线程,也就是在你调用启动线程之前,加上 t.daemon = True
。这样一来,这些线程就不会阻止程序停止了。