Python 高级编程--多线程编程(三)

    threading模块,它不仅提供了Thread类,还提供了各种非常好用的同步机制。

threading 模块里所有的对象:

Thread

表示一个线程的执行的对象。

Lock

锁原语对象(和Thread模块里的锁对象相同)

RLock

可重入锁对象。使单线程可以再次获得一件获得了的锁(递归锁定)。

Condition

条件变量对象能让一个线程停下来,等待其他线程满足了某个条件。如状态的改变或值的改变。

Event

通用的条件变量。多个线程可以等待某个事件的发生,在事件发生后,所有的线程都会被激活。

Semaphore

为等待锁的线程提供一个类似”等候室“的结构。

BoundedSemaphore

与Sempahore类似,只是它不允许超过初始值

Timer

与Thread相似,只是它要等待一段时间后才开始运行。

守护线程

一个避免使用Thread模块的原因是,它不支持守护线程。当主线程退出时,所有的子线程无论

它们是否还在工作,都会被强行退出。

Threading模块支持守护线程,它们是这样工作的:守护线程一般是一个等待客户请求服务器,如果没有

客户提出请求,它就在那等着。如果你设定一个线程为守护线程,就表示你在说这个线程不重要,在进程

退出的时候,不用等待这个线程退出。如果主线程退出不用等待那些子线程完成,那就设定这些线程的

daemon属性,即在线程thread.start()开始前,调用setDaemon()函数设定线程的daemon标志(thread.setDaemon(True))

就表示这个线程“不重要”。如果想要等待子线程完成再退出,那就什么都不用做或者显式地调用thread.setDaemon(False)

以保证其daemon标志为False,可以调用thread.isDaemon()函数来判断其daemon标志的值。新的子线程会继承

其父线程的daemon标志,整个Python会在所有的非守护线程退出后才会结束,即进程中没有非守护线程存在的时候才结束。

threading的Thread 类

Threading的Thread类是你主要的运行对象。它有很多Thread模块里没有的函数。如下:

函数描述
start()开始线程的执行
run()定义线程的功能的函数(一般会被子类重写)
join(timeout=None)程序挂起,直到线程结束;如果给了timeout,则最多阻塞timeout秒
getName()返回线程的名字
setName(name)设置线程的名字
isAlive()布尔标志,表示这个线程是否还在运行中
isDaemon()返回线程的daemon标志
setDaemon(daemonic)把线程的daemon标志设为daemonic(一定要在start函数前调用)
     用Thread类,你可以用多种方法来创建线程。这里介绍三种方法。

1)创建一个Thread的实例,传递它一个函数;

2)创建一个Thread的实例,传递它一个可调用的类对象;

3)从Thread派生出一个子类,创建一个这个子类的实例。

1).创建一个Thread实例,传给它一个函数

import  threading
import time

loops=[4,2]
def loop(nloop,nsesc):
    print 'start loop:',nloop,'at:',time.ctime()
    time.sleep(nsesc)
    print 'loop:',nloop,'done at:',time.ctime()
def main():
    print 'starting at:',time.ctime()
    threads=[]
    nloops=range(len(loops))
    for i in nloops:
        t=threading.Thread(target=loop,args=(i,loops[i]))
        threads.append(t)
        print t.getName()
    for j in nloops:    #start threads
        threads[j].start()

    for k in nloops:    #wait for all
        threads[k].join()  #threads to finish

    print 'done at:',time.ctime()
if __name__ == '__main__':
    main()
starting at: Wed Sep 13 09:40:13 2017
Thread-1
Thread-2
start loop: 0 at: Wed Sep 13 09:40:13 2017
start loop: 1 at: Wed Sep 13 09:40:13 2017
loop: 1 done at: Wed Sep 13 09:40:15 2017
loop: 0 done at: Wed Sep 13 09:40:17 2017
done at: Wed Sep 13 09:40:17 2017
    实例化一个Thread(调用 Thread())与调用thread.start_new_thread()之间最大的区别就是,新的线程不会立即开始。

在创建线程对象,但不想马上开始运行线程的时候,这是一个很有用的同步特性。所有的线程都创建了之后,再一起

调用 start()函数启动,而不是创建一个启动一个。而且也不用再管理一堆锁(分配锁、获得锁、释放锁、检查锁的状

态等),只要简单地对每个线程调用join()主线程等待子线程的结束即可。join()还可以设置timeout的参数,即主线程

等到超时为止。
   join()的另一个比较重要的方面是它可以完全不用调用,一旦线程启动后,就会一直运行,直到线程的函数结束,退出

为止。如果主线程除了等线程结束外,还有其它的事情要做,那就不用调用 join(),只有在等待线程结束的时候才调用join()。
  2).创建一个Thread的实例,传递它一个可调用的类对象

import threading
from time import sleep,ctime

loops=[4,2]
class ThreadFunc(object):
    def __init__(self,func,args,name):
        self.name=name
        self.func=func
        self.args=args

    def __call__(self):
        apply(self.func,self.args)

def loop(nloop,nsec):
    print 'start loop ',nloop,'at:',ctime()
    sleep(nsec)
    print 'loop',nloop,'done at:',ctime()

def main():
    print 'starting at:',ctime()
    threads=[]
    nloops=range(len(loops))
    for i in nloops: #create all threads
        t=threading.Thread(target=ThreadFunc(loop,(i,loops[i]),loop.__name__))
        threads.append(t)
    for i in nloops:    #start all threads
        threads[i].start()
    for i in nloops:    #wait for complet
        threads[i].join()
    print 'all done at:',ctime()
if __name__=='__main__':
    main()
starting at: Wed Sep 13 11:00:15 2017
start loop  0 at: Wed Sep 13 11:00:15 2017
start loop  1 at: Wed Sep 13 11:00:15 2017
loop 1 done at: Wed Sep 13 11:00:17 2017
loop 0 done at: Wed Sep 13 11:00:19 2017
all done at: Wed Sep 13 11:00:19 2017
    与传一个函数很相似的另一个方法是在创建线程的时候,传一个可调用的类的实例供线程启动的时候执行,这是多线程编程

的一个更为面向对象的方法。相对于一个或几个函数来说,类对象里可以使用类的强大的功能。创建新线程的时候,Thread

对象会调用ThreadFunc对象,这时会用到一个特殊函数__call__()。由于已经有了要用的参数,所以就不用再传到Thread()

的构造函数中。由于有一个参数的元组,这时要使用apply()函数或使用self.res = self.func(*self.args)。
  3).从Thread派生出一个子类,创建一个这个子类的实例

import threading
from time import sleep,ctime

loops=[4,2]
class MyThread(threading.Thread):
    def __init__(self,func,args,name=''):
        threading.Thread.__init__(self)
        self.name=name
        self.func=func
        self.args=args

    def getResult(self):
        return self.res

    def run(self):
        print 'starting',self.name,'at:',ctime()
        self.res=apply(self.func,self.args)
        print self.name,'finish at:',ctime()

def loop(nloop,nsec):
    print 'start loop ',nloop,'at:',ctime();
    sleep(nsec)
    print 'loop',nloop,'done at:',ctime()

def main():
    print 'starting at:',ctime()
    threads=[]
    nloops=range(len(loops))

    for i in nloops:
        t=MyThread(loop,(i,loops[i]),loop.__name__)
        threads.append(t)

    for i in nloops:
        threads[i].start()

    for i in nloops:
        threads[i].join()
    print 'all done at:',ctime()

if __name__=='__main__':
    main()
starting at: Wed Sep 13 13:14:32 2017
starting loop at: Wed Sep 13 13:14:32 2017
start loop  0 at:starting  Wed Sep 13 13:14:32 2017loop
 at: Wed Sep 13 13:14:32 2017
start loop  1 at: Wed Sep 13 13:14:32 2017
loop 1 done at: Wed Sep 13 13:14:34 2017
loop finish at: Wed Sep 13 13:14:34 2017
loop 0 done at: Wed Sep 13 13:14:36 2017
loop finish at: Wed Sep 13 13:14:36 2017
all done at: Wed Sep 13 13:14:36 2017
    子类化Thread类,MyThread子类的构造函数一定要先调用基类的构造函数,特殊函数__call__()在子类中,名字要改为run()。

在 MyThread类中,加入一些用于调试的输出信息,把代码保存到myThread模块中,并导入这个类。除使用apply()函数来

运行这些函数之外,还可以把结果保存到实现的self.res属性中,并创建一个新的函数getResult()来得到结果。

    threading模块中的其他函数

activeCount()

当前活动的前程对象的数量

currentThread()

返回当前线程对象

enumerate()

返回当前活动线程的列表

settrace()

为所有线程设置一个跟踪函数

setprofile()

为所有线程设置一个profile函数


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值