繁体   English   中英

Python关闭多个线程

[英]Python closing multiple Threads

我正在使用下面来自IBM网站的示例。 我注意到由于while循环,DatamineThread()和ThreadUrl()的线程保持打开状态。

我正在尝试终止这些线程并打印告诉我的内容。 我不确定是否要以正确的方式进行操作,或者不确定是否需要以这种方式终止线程。 问题是,当我在main()中将run设置为False时,while循环正在读取run = True。

任何帮助将是巨大的...谢谢

import Queue
import threading
import urllib2
import time
from BeautifulSoup import BeautifulSoup

hosts = ["http://yahoo.com", "http://google.com", "http://amazon.com",
        "http://ibm.com", "http://apple.com"]

queue = Queue.Queue()
out_queue = Queue.Queue()
run = True

class ThreadUrl(threading.Thread):
    """Threaded Url Grab"""
    def __init__(self, queue, out_queue):
        threading.Thread.__init__(self)
        self.queue = queue
        self.out_queue = out_queue

    def run(self):
        global run
        while run:
            #grabs host from queue
            host = self.queue.get()

            #grabs urls of hosts and then grabs chunk of webpage
            url = urllib2.urlopen(host)
            chunk = url.read()

            #place chunk into out queue
            self.out_queue.put(chunk)

            #signals to queue job is done
            self.queue.task_done()

        print 'ThreadUrl finished...'


class DatamineThread(threading.Thread):
    """Threaded Url Grab"""
    def __init__(self, out_queue):
        threading.Thread.__init__(self)
        self.out_queue = out_queue

    def run(self):
        global run
        while run:
            #grabs host from queue
            chunk = self.out_queue.get()

            #parse the chunk
            soup = BeautifulSoup(chunk)
            print soup.findAll(['title'])

            #signals to queue job is done
            self.out_queue.task_done()

        print 'DatamineThread finished...'

start = time.time()
def main():
    global run
    #spawn a pool of threads, and pass them queue instance
    for i in range(5):
        t = ThreadUrl(queue, out_queue)
        t.setDaemon(True)
        t.start()

    #populate queue with data
    for host in hosts:
        queue.put(host)

    for i in range(5):
        dt = DatamineThread(out_queue)
        dt.setDaemon(True)
        dt.start()


    #wait on the queue until everything has been processed
    queue.join()
    out_queue.join()

    # try and break while-loops in threads
    run = False

    time.sleep(5)


main()
print "Elapsed Time: %s" % (time.time() - start)

我个人不是线程条件全局变量的忠实拥护者,很大程度上是因为我之前已经看过您遇到的情况。 原因来自Queue.get的python文档。

如果可选的args块为true,并且超时为None(默认值),则在必要时阻塞,直到有可用项为止。

本质上,您永远不会while run:看到第二次检查while run:因为out_queue.get()在队列清空后无限期地阻塞。

更好的方法,恕我直言,要么在队列中使用哨兵值,要么使用get_nowait并捕获异常以打破循环。 例子:

哨兵

class DatamineThread(threading.Thread):
    def run(self):
        while True:
            data = self.out_queue.get()
            if data == "time to quit": break
            # non-sentinel processing here.

尝试/除外

class DatamineThread(threading.Thread):
    def run(self):
        while True:
            try:
                data = self.out_queue.get_nowait() # also, out_queue.get(False)
            except Queue.Empty: break
            # data processing here.

为确保所有线程结束,可以采用以下几种方法:

为每个工人添加哨兵

for i in range(numWorkers):
  out_queue.put('time to quit')

out_queue.join()

更换前哨

class DatamineThread(threading.Thread):
    def run(self):
        while True:
            data = self.out_queue.get()
            if data == "time to quit": 
                self.out_queue.put('time to quit')
                break
            # non-sentinel processing here.

两种方法都应该起作用。 首选哪种方式取决于out_queue的填充方式。 如果可以通过工作线程将其添加/删除,则首选第一种方法。 调用join() ,然后添加标记,然后再次调用join() 如果您不想记住您创建了多少个工作线程,则第二种方法很好-它仅使用一个哨兵值并且不会使队列混乱。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM