efeve 2012-12-29
Python多线程学习-threading
想学习python多线程,可以直接看官网http://docs.python.org/2/library/threading.html
Python的文档真心是值得称赞的,不过你如果不想看英文,直接向入门python多线程,本文可以作为你快速入门的捷径。
先打开python command端口,输入
import threading
Ok,如果没有什么输出,那么就是import成功了。
根据学习的过程并且你如果看过上一篇文章的话,先来下dir命令
dir(threading) BoundedSemaphore Condition Event Lock RLock Semaphore Thread ThreadError Timer
这些是threading包提供的一些多线程模块,看到其中的Thread,有没有感觉很眼熟。
这个Thread对于Java的同学来说是个福音,因为使用这个Thread和Java没有什么不同,至少思路一致。
对于threading模块的这些模块,我们后面都会讲到
threading包除了这些模块外,还提供了一些方法,
threading.enumerate() 返回当前存活的Thread列表 threading.active_count() threading.activeCount() 返回当前的依然存活的Thread数量,实际上就是enumerate()返回的长度 threading.current_thread() threading.current_Thread() 返回当前的线程,根据调用线程的不同返回不同值 threading.local 表示thread-local量,Thread-Local数据是跟Thread相关的
上面这些都是和threading包的内容,实际是保存了当前main thread的宏观信息,明白这个就好。
下面我们来学习Thread模块,按照惯例,执行dir命令
dir(threading.Thread) daemon getName ident isAlive isDaemon is_alive join name run setDaemon setName start
可以看到,Thread有几个重要的属性,daemon、name、alive、ident
daemon:这个参数很关键。在调用start前设置改值,默认主线程创建的子线程都是False,表示主线程必须等子线程完成才能退出;如果为True的话,主线程退出导致子线程立即退出,根据自己的应用场景设置合适的True或者False。
name:thread name
alive:ture or false
ident:identity
看到run和join方法了吗?这个有没有很熟悉。下面我们来看下通过继承threading.Thread 来创建线程的方法。
#!/usr/bin/python import threading import time class my_thread(threading.Thread): def __init__(self,threadname,interval): threading.Thread.__init__(self,name=threadname) self.interval=interval def run(self): print dir(self) for i in range(10): print self.getName,i time.sleep(self.interval) if __name__ == "__main__": mythread=my_thread("thread one",3) mythread2=my_thread("thread two",5) mythread.start() mythread2.start()
下面我们再看下用另一种方法来创建线程的方法
#!/usr/bin/python import threading import time def run(interval): for i in range(5): print threading.current_thread().getName(),i time.sleep(interval) if __name__ == "__main__": for i in range(3): threading.Thread(target=run,args=[5],name='thread-' + str(i)).start()
对于这种方法创建的线程,我们看下init函数:
def __init__(self, group=None, target=None, name=None, args=(), kwargs={}) group:预留 target:是一个可调用对象(也称为活动[activity]),在线程启动后执行; name:是线程的名字。默认值为“Thread-N“,N是一个数字。 args和kwargs:表示调用target时的参数列表和关键字参数。
看使用方法,应该是使用第一种更为方便
我们先看下daemon的用法:
import threading import datetime from time import sleep import sys class threadclass(threading.Thread): def run(self): print self.daemon for i in range(10): now=datetime.datetime.now() print "%s says hello world at time:%s" %(self.getName(),now) sleep(1) if __name__ == "__main__": t=threadclass(); t.daemon=True t.start() sleep(5) sys.exit(0)
可以看到执行了五次后就退出了,主线程推出子线程也就退出了。
可以再将t.daemon=True注掉后再运行一下,对比下结果。
关于join的用法,如果在主线程中调用这个方法,会等子线程执行完成后主线程才会退出来。
这个join用法和daemon参数是有冲突的,不过一般不会同时设置daemon参数和调用join方法
有了Thread结构,后面的工作就很简单啦。
下面我们再看下threading.Timer的用法。
#!/usr/bin/python import threading import time def run(): print "hello word"; if __name__ == "__main__": t=threading.Timer(5.0,run) t.start()
Timer的用法比较简单,就是设定一个时间点interval,等到时间间隔到了后,执行function
并没有想你想象的那么大的功能,如Java的Timer、Quartz的Scheduler等。
这个Timer的功能从初始化函数可以看出来:
def __init__(self, interval, function, args=[], kwargs={}): interval:时间间隔 function:执行函数 args、kwargs:函数执行参数
本节我们学习了Thread、Timer两个模型,下节课我们学习别的内容