核心提示:守护线程
另一个避免使用thread 模块的原因是,它不支持守护线程。当主线程退出时,所有的子线程不论它们是否还在工作,都会被强行退出。有时,我们并不期望这种行为,这时,就引入了守护线程的概念
threading 模块支持守护线程,它们是这样工作的:守护线程一般是一个等待客户请求的服务器,如果没有客户提出请求,它就在那等着。如果你设定一个线程为守护线程,就表示你在说这个线程是不重要的,在进程退出的时候,不用等待这个线程退出。就像你在第16 章网络编程看到的,服务器线程运行在一个无限循环中,一般不会退出。
另一个避免使用thread 模块的原因是,它不支持守护线程。当主线程退出时,所有的子线程不论它们是否还在工作,都会被强行退出。有时,我们并不期望这种行为,这时,就引入了守护线程的概念
threading 模块支持守护线程,它们是这样工作的:守护线程一般是一个等待客户请求的服务器,如果没有客户提出请求,它就在那等着。如果你设定一个线程为守护线程,就表示你在说这个线程是不重要的,在进程退出的时候,不用等待这个线程退出。就像你在第16 章网络编程看到的,服务器线程运行在一个无限循环中,一般不会退出。
如果你的主线程要退出的时候,不用等待那些子线程完成,那就设定这些线程的daemon 属性。即,在线程开始(调用thread.start())之前,调用setDaemon()函数设定线程的daemon 标志(thread.setDaemon(True))就表示这个线程“不重要”。
如果你想要等待子线程完成再退出, 那就什么都不用做, 或者显式地调用thread.setDaemon(False)以保证其daemon 标志为False。你可以调用thread.isDaemon()函数来判断其daemon 标志的值。新的子线程会继承其父线程的daemon 标志。整个Python 会在所有的非守护线程退出后才会结束,即进程中没有非守护线程存在的时候才结束。
threading 的Thread 类是你主要的运行对象。它有很多thread 模块里没有的函数。用Thread 类,你可以用多种方法来创建线程。我们在这里介绍三种比较相像的方法。你可以任选一种你喜欢的,或最适合你的程序以及最能满足程序可扩展性的(我们一般比较喜欢最后一个选择):
1. 创建一个 Thread 的实例,传给它一个函数
2. 创建一个 Thread 的实例,传给它一个可调用的类对象
3. 从 Thread 派生出一个子类,创建一个这个子类的实例
方法一的例子如下:
#!/usr/bin/env python
#coding:utf-8
import threading
from time import sleep,ctime
loops=[4,2]
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))
print nloops
for i in nloops:
#创建一个 Thread 的实例,传给它一个函数,target表示函数名,args是要传给loop函数的所有参数
t=threading.Thread(target=loop,args=(i,loops[i]))
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()
方法二: 创建一个 Thread 的实例,传给它一个可调用的类对象
#!/usr/bin/env python
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:
t=threading.Thread(target=ThreadFunc(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()