Python多线程学习-壹-threading

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两个模型,下节课我们学习别的内容

相关推荐