线程中的流控制

3 投票
3 回答
1904 浏览
提问于 2025-04-15 14:28

我遇到了一些关于使用线程模块(在Python 2.6中)管理线程的例子。

我想弄明白的是,这个例子是怎么调用“run”方法的,以及在哪里调用的。我在任何地方都没有看到它。ThreadUrl类在main()函数中被实例化为“t”,我通常会在这里期待代码开始调用“run”方法。

也许这不是处理线程的推荐方式?请给我一些启发:

#!/usr/bin/env python

import Queue
import time
import urllib2
import threading
import datetime

hosts = ["http://example.com/", "http://www.google.com"]

queue = Queue.Queue()

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

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

                    #grabs urls of hosts and prints first 1024 bytes of page
                    url = urllib2.urlopen(host)
                    print url.read(10)

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

start = time.time()

def main():

    #spawn a pool of threads, and pass them queue instance
    for i in range(1):
            t = ThreadUrl(queue)
            t.setDaemon(True)
            t.start()

            for host in hosts:
                    queue.put(host)

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

3 个回答

0

t.start() 这个命令会在操作系统中创建一个新的线程。当这个线程开始运行时,它会调用这个线程的 run() 方法(或者如果你在 Thread 构造函数中提供了一个 target,它会调用你提供的那个函数)。

4

run()这个方法是由“threading.Thread”在后台自动调用的(可以查一下面向对象编程中的继承和多态的概念)。这个调用会在你执行t.start()之后进行。

如果你能访问到threading.py文件(在Python的安装文件夹里可以找到),你会看到一个叫做Thread的类。在这个类里,有一个叫做“start()”的方法。start()会调用一个低级的线程启动方法'_start_new_thread(self.__bootstrap, ())',这个方法会通过一个新线程运行一个叫做'__bootstrap()'的包装方法。接着,'__bootstrap()'会调用'__bootstrap_inner()',这个方法会做一些额外的准备工作,最后才会调用'run()'。

阅读源代码,你会学到很多东西。:D

7

根据pydoc的说明:

Thread.start()

启动线程的活动。

这个方法每个线程对象最多只能调用一次。它会安排在一个单独的控制线程中调用这个对象的 run() 方法。

如果在同一个线程对象上调用超过一次,这个方法会抛出一个运行时异常。

可以把Python的Thread对象想象成,它会把一些同步编写的Python代码(可以是在run方法里,或者通过target参数传入的代码)包装成C代码,这样就能让它异步运行。这样做的好处是,你可以把start当作一个不透明的方法来使用:除非你在用C重写这个类,否则你不需要去重写它,但你可以很具体地使用run。这在你想要同步测试线程逻辑的时候特别有用。你只需要调用t.run(),它就会像其他方法一样执行。

撰写回答