最新消息:

Python线程样例

未分类 admin 2757浏览 0评论
import threading
import time

count = 1

class KissThread(threading.Thread):
    def run(self):
        global count
        print "%s # %s: Pretending to do stuff" % (self.name, count)
        time.sleep(2)
        print "done with stuff # %s" % self.name

if __name__ == '__main__':
    for i in range(5):
        KissThread().start()

这里可以看出threading.Thread()实例有两个方法,一个start(),一个run(),其中,start()方法启动一个新线程。这个新线程运行线程的run()方法。threading.Thread()实例的start()方法,相当于是vfork(),然后执行clone()出来的threading.Thread().run()。
这个例子本来是抄书上的,但是发现有问题,因为并发、多线程编程时,必需要考虑“同步”问题。比如上面的例子,本意是按顺序输出count的值,但实际上,有可能会输出相同的count值:

$ python threading_test.py
Thread-1 # 1: Pretending to do stuff
Thread-2 # 2: Pretending to do stuff
Thread-3 # 2: Pretending to do stuff
Thread-4 # 4: Pretending to do stuff
Thread-5 # 5: Pretending to do stuff
Thread-1 done with stuff
Thread-3 done with stuff
Thread-2 done with stuff
Thread-4 done with stuff
Thread-5 done with stuff

即,并发、多线程运行的代码,运行顺序不可预测。即threading.Thread().run()中的代码行的执行顺序,不可预测。所以count的值,并不像想象中的按顺序输出。
但是,线程可以共享数据,比较全局变量。这样“进程间通信”问题变得容易了。但是因此而带的问题,需要特别注意,否则程序往往是错的。

from threading import Thread
from Queue import Queue
import subprocess
import sys

def pinger(i, queue):
    while True:
        ip = queue.get()
        print "Thread %s: Pinging %s" % (i, ip)
        ret = subprocess.call("ping -c2 -w2 %s" % ip,
                               shell=True,
                               stdout=open('/dev/null','w'),
                               stderr=subprocess.STDOUT)

        if ret == 0:
            print "%s : is alive" % ip
        else:
            print "%s : did not respond" % ip

        queue.task_done()

if __name__ == '__main__':
    queue = Queue()
    for i in range(5):
        worker = Thread(target=pinger, args=(i,queue))
        worker.setDaemon(True)
        worker.start()

    for i in open(sys.argv[1], 'r'):
        queue.put(i.strip())

    print "Main Thread Waiting"
    queue.join()
    print "Done"

1. 线程实例化时的两个常用参数:
target,函数对象,注意是函数对象,是函数名pinger,不是运行函数pinger(),是线程start()之后,运行的代码。
args,参数元组,target实例化(函数实例化,就是运行函数)时传递给target的参数。target需要两个变量。通常第二个变量是队列。
见Thread类的定义:

__init__(self, group=None, target=None, name=None,
 	args=(), kwargs=None, verbose=None)

run()/target的定义:

    def run(self):
        try:
            if self.__target:
                self.__target(*self.__args, **self.__kwargs)
        finally:
            # Avoid a refcycle if the thread is running a function with
            # an argument that has a member that points to the thread.
            del self.__target, self.__args, self.__kwargs

2. queue=Queue()
queue.task_done()类似于队列计数减1,queue.join()类似于“当队列计数为0时,返回;并不断检查、重试”。

转载请注明:爱开源 » Python线程样例

您必须 登录 才能发表评论!