首先看一个简单的没有线程支持的情况下的顺序执行:
<span style="font-size:18px;">from time import sleep, ctime
def loop0():
print('start loop 0 at:', ctime())
sleep(4)
print('loop 0 done at:', ctime())
def loop1():
print('start loop 1 at:', ctime())
sleep(4)
print('loop 1 done at:', ctime())
def main():
print('starting at:', ctime())
loop0()
loop1()
print('all DONE at:', ctime())
if __name__ == '__main__':
main()</span>
在这个程序中,loop0 先执行,loop1后执行,其结果如下所示:
如果想要并行执行,需加入threading模块的支持,模块的对象有如下几个:
模块中的主要函数有:
- 是你主要的线程类,可以创建进程实例。该类提供的函数包括:
- getName(self) 返回线程的名字
- isAlive(self) 布尔标志,表示这个线程是否还在运行中
- isDaemon(self) 返回线程的daemon标志
- join(self, timeout=None) 程序挂起,直到线程结束,如果给出timeout,则最多阻塞timeout秒
- run(self) 定义线程的功能函数
- setDaemon(self, daemonic) 把线程的daemon标志设为daemonic
- setName(self, name) 设置线程的名字
- start(self) 开始线程执行
<span style="font-size:18px;">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))
for i in nloops:
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()</span>
在本例中,启动loop0线程和loop1线程,并发执行,执行结果如图:
通过观察执行结果可看到,41-43秒loop0和loop1都在执行,其中loop1从41秒执行到43共2秒,loop0从41到45共4秒。
为了使程序更有面向对象的概念,在下个程序中增加了ThreadFunc类和创建Thread对象时实例化一个可调用的ThreadFunc的类对象,代码如下:
<span style="font-size:18px;">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):
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 completion
threads[i].join()
print('all DONE at:', ctime())
if __name__ == '__main__':
main()</span>
这样通过传入一个可以调用的类的实例,而不仅仅是传入一个函数,更具面向对象的概念,运行结果如下:
下面通过一个计算斐波那契、阶乘、累加和三个函数在单线程和多线程中运行来说明多线程的好处。
我们现在要子类化Thread类,以更加灵活的定制线程对象。
myThread子类模块如下:
<span style="font-size:18px;">import threading
from time import time, ctime
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 = self.func(*self.args)
print(self.name, 'finished at:',
ctime())</span>
主程序模块如下:
<span style="font-size:18px;">from myThread import MyThread
from time import ctime, sleep
def fib(x):
sleep(0.005)
if x < 2: return 1
return (fib(x-2) + fib(x-1))
def fac(x):
sleep(0.1)
if x < 2: return 1
return (x * fac(x-1))
def sum(x):
sleep(0.1)
if x < 2: return 1
return (x + sum(x-1))
funcs = (fib, fac, sum)
n = 12
def main():
nfuncs = range(len(funcs))
print('*** SINGLE THREAD')
for i in nfuncs:
print('starting', funcs[i].__name__,
'at:', ctime())
print(funcs[i](n))
print(funcs[i].__name__, 'finished at:',
ctime())
print('\n*** MULTIPLE THREADS')
threads = []
for i in nfuncs:
t = MyThread(funcs[i], (n,),
funcs[i].__name__)
threads.append(t)
for i in nfuncs:
threads[i].start()
for i in nfuncs:
threads[i].join()
print(threads[i].getResult())
print('all DONE')
if __name__ == '__main__':
main()</span>
程序运行结果如下:
参考资料:《Python核心编程》
实例代码下载:https://github.com/wlseu/pythread