Python 多线程编程,thread

来源:互联网 发布:大叔与女孩的网络电影 编辑:程序博客网 时间:2024/05/16 07:27

Python提供了thread模块,threading模块与queue模块进行多线程编程。queue模块用于线程间的通信,前两者可以创建线程,不过由于thread模块偏底层,需要手动去完成很多任务,而且同步机制不如threading模块好用,所以建议选择threading模块。

        threading模块中,选择Thread类来创建线程(三种方法):创建一个Thread的实例,并传入一个函数;创建一个Thread的实例,并传入一个可调用的类对象;从Thread派生出一个子类,创建一个这个子类的实例。(代码来自core Python programming)(Python3.3)

创建一个Thread的实例,并传入一个函数:

[python] view plaincopy
  1. import threading  
  2. from time import sleep,ctime  
  3.   
  4. loops=[4,2]  
  5.   
  6. def loop(nloop, nsec):  
  7.     print('start loop',nloop,'at',ctime())  
  8.     sleep(nsec)  
  9.     print('loop',nloop,'done at:',ctime())  
  10.   
  11. def test():  
  12.     print('starting at:',ctime())  
  13.     threads=[]  
  14.     nloops=range(len(loops))  
  15.   
  16.     for i in nloops:  
  17.         t=threading.Thread(target=loop,args=(i,loops[i]))  
  18.         threads.append(t)  
  19.   
  20.     for i in nloops:  
  21.         threads[i].start()  
  22.   
  23.     for i in nloops:  
  24.         threads[i].join() #当前process或者thread遇到join()函数时会暂停(挂起),直到这个join()函数连接的thread结束;join(timeout=None)中的timeout参数如果设置了,则会等到设置的时间长度,直到超时或者thread结束,开始运行接下来的代码  
  25.   
  26.     print('all done at',ctime())  
  27.   
  28. if __name__=='__main__':  
  29.     test()  

结果:

[python] view plaincopy
  1. >>>   
  2. starting at: Thu Aug 15 01:34:20 2013  
  3. start loopstart loop  01  atat  Thu Aug 15 01:34:20 2013Thu Aug 15 01:34:20 2013  
  4.   
  5. loop 1 done at: Thu Aug 15 01:34:22 2013  
  6. loop 0 done at: Thu Aug 15 01:34:24 2013  
  7. all done at Thu Aug 15 01:34:25 2013  

创建一个Thread的实例,并传入一个可调用的类对象:
较第一种更面向对象一点,更灵活。

[python] view plaincopy
  1. import threading  
  2. from time import sleep,ctime  
  3.   
  4. loops=[4,2]  
  5.   
  6. class ThreadFunc(object):  
  7.     def __init__(self,func,args,name=''):  
  8.         self.name=name  
  9.         self.func=func  
  10.         self.args=args  
  11.   
  12.     def __call__(self):  
  13.         self.func(*self.args)  
  14.   
  15. def loop(nloop, nsec):  
  16.     print('start loop',nloop,'at',ctime())  
  17.     sleep(nsec)  
  18.     print('loop',nloop,'done at:',ctime())  
  19.   
  20. def test():  
  21.     print('starting at:',ctime())  
  22.     threads=[]  
  23.     nloops=range(len(loops))  
  24.   
  25.     for i in nloops:  
  26.         t=threading.Thread(target=ThreadFunc(loop,(i,loops[i]),loop.__name__))  
  27.         threads.append(t)  
  28.   
  29.     for i in nloops:  
  30.         threads[i].start()  
  31.   
  32.     for i in nloops:  
  33.         threads[i].join()  
  34.   
  35.     print('all done at',ctime())  
  36.   
  37. if __name__=='__main__':  
  38.     test()  

结果:

[python] view plaincopy
  1. >>>   
  2. starting at: Thu Aug 15 01:58:32 2013  
  3. start loopstart loop  01  atat  Thu Aug 15 01:58:32 2013Thu Aug 15 01:58:32 2013  
  4.   
  5. loop 1 done at: Thu Aug 15 01:58:34 2013  
  6. loop 0 done at: Thu Aug 15 01:58:36 2013  
  7. all done at Thu Aug 15 01:58:36 2013  

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

[python] view plaincopy
  1. import threading  
  2. from time import sleep,ctime  
  3.   
  4. loops=[4,2]  
  5.   
  6. class MyThread(threading.Thread):  
  7.     def __init__(self,func,args,name=''):  
  8.         threading.Thread.__init__(self)  
  9.         self.name=name  
  10.         self.func=func  
  11.         self.args=args  
  12.   
  13.     def run(self):  
  14.         self.func(*self.args)  
  15.   
  16. def loop(nloop, nsec):  
  17.     print('start loop',nloop,'at',ctime())  
  18.     sleep(nsec)  
  19.     print('loop',nloop,'done at:',ctime())  
  20.   
  21. def test():  
  22.     print('starting at:',ctime())  
  23.     threads=[]  
  24.     nloops=range(len(loops))  
  25.   
  26.     for i in nloops:  
  27.         t=MyThread(loop,(i,loops[i]),loop.__name__)  
  28.         threads.append(t)  
  29.   
  30.     for i in nloops:  
  31.         threads[i].start()  
  32.   
  33.     for i in nloops:  
  34.         threads[i].join()  
  35.   
  36.     print('all done at',ctime())  
  37.   
  38. if __name__=='__main__':  
  39.     test()  

结果:

[python] view plaincopy
  1. >>>   
  2. starting at: Thu Aug 15 02:15:18 2013  
  3. start loopstart loop 1  at Thu Aug 15 02:15:18 2013  
  4. 0 at Thu Aug 15 02:15:18 2013  
  5. loop 1 done at: Thu Aug 15 02:15:20 2013  
  6. loop 0 done at: Thu Aug 15 02:15:22 2013  
  7. all done at Thu Aug 15 02:15:22 2013  

单线程、多线程速度对比:

对多线程使用第三者创建线程的方法。计算斐波纳挈、阶乘、累加和的结果:

首先,编写一个单独的模块myThread.py,专门生成线程,然后使用的时候,只需要import myThread 就可以了。

[python] view plaincopy
  1. import threading  
  2. from time import sleep,ctime  
  3.   
  4. class MyThread(threading.Thread):  
  5.     def __init__(self,func,args,name=''):  
  6.         threading.Thread.__init__(self)  
  7.         self.name=name  
  8.         self.func=func  
  9.         self.args=args  
  10.   
  11.     def getResult(self):  
  12.         return self.res  
  13.     def run(self):  
  14.         print('starting',self.name,'at:',ctime())  
  15.         self.res=self.func(*self.args)  
  16.         print(self.name,'finished at:',ctime()) #end of module myThread  
创建线程并计算:

[python] view plaincopy
  1. from myThread import MyThread  
  2. from time import ctime,sleep  
  3.   
  4. def fib(x):  
  5.     sleep(0.005)  
  6.     if x<2:  
  7.         return 1  
  8.     return (fib(x-2)+fib(x-1))  
  9.   
  10. def fac(x):  
  11.     sleep(0.1)  
  12.     if x<2:  
  13.         return 1  
  14.     return (x*fac(x-1))  
  15.   
  16. def sumF(x):  
  17.     sleep(0.1)  
  18.     if x<2:  
  19.         return 1  
  20.     return (x+sumF(x-1))  
  21.   
  22. funcs=[fib, fac, sumF]  
  23. n=12  
  24.   
  25. def test():  
  26.     nfuncs=range(len(funcs))  
  27.   
  28.     print('***SINGLE THREAD')  
  29.     for i in nfuncs:  
  30.         print('starting',funcs[i].__name__,'at:',ctime())  
  31.         print(funcs[i](n))  
  32.         print(funcs[i].__name__,'finished at:',ctime())  
  33.   
  34.     print('\n***MULTIPLE THREADS')  
  35.     threads=[]  
  36.     for i in nfuncs:  
  37.         t=MyThread(funcs[i],(n,),funcs[i].__name__)  
  38.         threads.append(t)  
  39.   
  40.     for i in nfuncs:  
  41.         threads[i].start()  
  42.   
  43.     for i in nfuncs:  
  44.         threads[i].join()  
  45.         print(threads[i].getResult())  
  46.   
  47.     print('All done.')  
  48.   
  49. if __name__=='__main__':  
  50.     test()  

结果:

[python] view plaincopy
  1. >>>   
  2. ***SINGLE THREAD  
  3. starting fib at: Thu Aug 15 05:15:10 2013  
  4. 233  
  5. fib finished at: Thu Aug 15 05:15:13 2013  
  6. starting fac at: Thu Aug 15 05:15:13 2013  
  7. 479001600  
  8. fac finished at: Thu Aug 15 05:15:14 2013  
  9. starting sumF at: Thu Aug 15 05:15:14 2013  
  10. 78  
  11. sumF finished at: Thu Aug 15 05:15:15 2013  
  12.   
  13. ***MULTIPLE THREADS  
  14. startingstartingstarting   fibfacsumF   at:at:at:   Thu Aug 15 05:15:15 2013Thu Aug 15 05:15:15 2013Thu Aug 15 05:15:15 2013  
  15.   
  16.   
  17. facsumF  finished at:finished at:  Thu Aug 15 05:15:16 2013Thu Aug 15 05:15:16 2013  
  18.   
  19. fib finished at: Thu Aug 15 05:15:17 2013  
  20. 233  
  21. 479001600  
  22. 78  
  23. All done.  

queue模块进行线程间通信:

[python] view plaincopy
  1. import random  
  2. from time import sleep  
  3. from queue import Queue  
  4. from myThread import MyThread  
  5.   
  6. def writeQ(queue):  
  7.     print('producting object for Q...')  
  8.     queue.put('xxx',1#第一个参数为要写入Queue的数据,第二个参数为默认值,表示当Queue满的时候,会使线程暂停,直到空出一个位置  
  9.     print('size now',queue.qsize())  
  10.   
  11. def readQ(queue):  
  12.     val=queue.get(1#这个参数为默认参数,表示当Queue为空时,线程暂停,直到有了一个数据  
  13.     print('consumed object from Q... size now',queue.qsize())  
  14.   
  15. def writer(queue,loops):  
  16.     for i in range(loops):  
  17.         writeQ(queue)  
  18.         sleep(random.randint(1,3))  
  19.   
  20. def reader(queue,loops):  
  21.     for i in range(loops):  
  22.         readQ(queue)  
  23.         sleep(random.randint(2,5))  
  24.   
  25. funcs=[writer,reader]  
  26. nfuncs=range(len(funcs))  
  27.   
  28. def test():  
  29.     nloops=random.randint(2,5#表示读与写的次数,读写次数相同  
  30.     q=Queue(32)  
  31.   
  32.     threads=[]  
  33.     for i in nfuncs:  
  34.         t=MyThread(funcs[i],(q,nloops),funcs[i].__name__)  
  35.         threads.append(t)  
  36.   
  37.     for i in nfuncs:  
  38.         threads[i].start()  
  39.   
  40.     for i in nfuncs:  
  41.         threads[i].join()  
  42.   
  43.     print('All done.')  
  44.   
  45. if __name__=='__main__':  
  46.     test()  
  47.       

结果:

[python] view plaincopy
  1. >>>   
  2. startingstarting  writerreader  at:at:  Thu Aug 15 05:57:00 2013Thu Aug 15 05:57:00 2013  
  3.   
  4. producting object for Q...  
  5. size nowconsumed object from Q... size now  10 #这里不是10,而是一个1,一个0.1上writeQ()输出的,0是readQ()输出的  
  6.   
  7. producting object for Q...  
  8. size nowconsumed object from Q... size now  10  
  9.   
  10. producting object for Q...  
  11. size now 1  
  12. writer finished at: Thu Aug 15 05:57:06 2013  
  13. consumed object from Q... size now 0  
  14. reader finished at: Thu Aug 15 05:57:10 2013  
  15. All done.  
0 0
原创粉丝点击