案例应用
(1)、T1、创建Thread实例,传给它一个函数
#T1、创建Thread实例,传给它一个函数
import threading
from time import sleep, ctime
loops = [2,4] #睡眠时间
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 = [] #添加了一些Thread对象
nloops = range(len(loops)) #列表[0,1]
#创建线程:在实例化每个Thread对象时,把函数(target)和参数(args)都传进去,得到返回的Thread实例。
for i in nloops:
#实例化一个Thread调用Thread()方法与调用thread.start_new_thread()之间的最大区别是:
#新的线程不会立即开始。在你创建线程对象,但不想马上开始运行线程的时候,这是一个很有用的同步特性。
t = threading.Thread(target=loop,args=(i,loops[i]))
threads.append(t)
#开始线程:Change1:所有的线程都创建之后,再一起调用start()函数启动线程,而不是创建一个启动一个。
for i in nloops:
threads[i].start()
#等待所有结束线程:threading模块的Thread类有一个join()函数,允许主线程等待线程的结束。
#Change2:不用再管理一堆锁(分配锁、获得锁、释放锁、检查锁的状态等),只要简单地对每个线程调用join()函数就可以了。
# 使用join()比使用一个等待锁释放的无限循环清楚一些(也称“自旋锁”)。
#Tip:如果你的主线程除了等线程结束外,还有其他的事情要做(如处理或等待其他的客户请求),那就不用调用join(),只有在你要等待线程结束的时候才要调用join()。
for i in nloops:
threads[i].join()
print('All end:', ctime())
if __name__ == '__main__':
main()
(2)、T2、创建一个Thread实例,传给它一个可调用的类对象。
这个方法,与T1方法传递一个函数很相似。但它是传一个可调用的类的实例供线程启动的时候执行,这是多线程编程的一个更为面向对象的方法。相对于一个或几个函数来说,由于类对象里可以使用类请打的功能,可以保存更多的信息,这种方法更为灵活。
#T2、创建一个Thread实例,传给它一个可调用的类对象
#coding=utf-8
import threading
from time import sleep, ctime
loops = [2,4] #睡眠时间
#创建Thread对象时会实例化一个可调用类ThreadFunc的类对象。这个类保存了函数的参数,函数本身以及函数的名字字符串
class ThreadFunc(object): #传递的是一个可调用的类,而不是一个函数
def __init__(self, func, args, name=''): #构造器__init__()函数:初始化赋值工作
self.name=name
self.func=func
self.args=args
def __call__(self): #特殊函数__call__():由于我们已经有要用的参数,所以就不用再传到Thread()构造器中;
#由于我们有一个参数的元组,这时python2要在代码中使用apply()函数即Python3中改为下边。
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)) #列表[0,1]
for i in nloops:
#调用ThreadFunc类实例化的对象,创建所有线程
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 end:', ctime())
if __name__ == '__main__':
main()
#Python2中的apply函数的讲解
#apply(func [, args [, kwargs ]]) 函数:用于当函数参数已经存在于一个元组或字典中时,间接地调用函数。
# args是一个包含将要提供给函数的按位置传递的参数的元组。如果省略了args,任何参数都不会被传递,
# kwargs是一个包含关键字参数的字典。
def say(a, b):
print(a, b)
apply(say,("第一个参数", "Python线程")) #输出得到:第一个参数 Python线程