python多线程

    python3中支持多线程的目前有threading和Queue模块,之前的thread模块已经从最新的python3中移除,找不到。相比于以前的thread模块,threading模块更安全拥有更多的同步机制,可以提供更多的方法。

       threading模块中支持守护线程,守护线程是一个等待客户端请求服务的服务器,如果没有客户端的请求,守护线程就是空闲的。若把一个守护线程设置为守护线程,那么这个线程就是不重要的,进程退出的时候不需要等待这线程执行完成。在主线程准备退出时候,不需要等待某些子线程完成,那么就可以把这些子线程设置为守护线程标记,为True表示该线程不重要,或者是该线程是为了等待客户端的请求而不做任何其他的事情。

       在threading模块中我们主要使用thread类,thread类有很多的方法创建线程,主要有:

1.创建thread的实例,传递一个函数

2.创建thread的实例,传递一个可调用的类实例

3.派生thread的子类,并且创建子类的实例

(1)在单线程条件下:

[python]  view plain  copy
  1. #!/usr/bin/env python3  
  2. # -*- coding: utf-8 -*-  
  3. """ 
  4. Created on Thu Jan 11 16:51:18 2018 
  5.  
  6. @author: lisir 
  7. """  
  8.   
  9. from time import sleep  
  10. from time import ctime  
  11.   
  12. def loop0():  
  13.     print('start loop 0 at :', ctime())  
  14.     sleep(4)  
  15.     print('loop 0 done at :', ctime())  
  16.       
  17. def loop1():  
  18.     print('start loop 1 at :', ctime())  
  19.     sleep(2)  
  20.     print('loop 1 done at :', ctime())  
  21.       
  22. def main():  
  23.     print('starting at: ', ctime())  
  24.     loop0()  
  25.     loop1()  
  26.     print('all done at :', ctime())  
  27.       
  28. if __name__ == '__main__':  
  29.     main()  

(2)创建thread的实例,传递一个函数

[python]  view plain  copy
  1. #!/usr/bin/env python3  
  2. # -*- coding: utf-8 -*-  
  3. """ 
  4. Created on Thu Jan 11 16:51:18 2018 
  5.  
  6. @author: lisir 
  7. """  
  8. import threading  
  9. from time import sleep  
  10. from time import ctime  
  11.   
  12. loops = [42]  
  13.   
  14. def loop(nloop, nsec):  
  15.     print('start loop :', nloop, ' at: ', ctime())  
  16.     sleep(nsec)  
  17.     print('loop ', nloop, ' done at : ', ctime())  
  18.       
  19. def main():  
  20.     print('starting at: ', ctime())  
  21.     threads = []  
  22.     nloops = range(len(loops))  
  23.     for i in nloops:  
  24.         t = threading.Thread(target=loop,args=(i, loops[i]))  
  25.         threads.append(t)  
  26.     # start threads  
  27.     for i in nloops:  
  28.         threads[i].start()  
  29.     # wait for all threads to finish  
  30.     for i in nloops:  
  31.         threads[i].join()  
  32.       
  33.     print('all done at :', ctime())  
  34.       
  35. if __name__ == '__main__':  
  36.     main()  

       此时的总体程序执行时间受限于“木桶效应”。总体时间相比单线程减少2s,总体时间决定于最长的哪个线程执行时间。实例化thread对象的时候,把函数target和参数args传递进去,然后返回thread的实例。在这里,实例化thread和调用thread.start_new_thread()的最大区别在于新的线程并不会立即去执行,在我们不希望线程立即执行的时候非常有用。当所有的线程都分配完成后,通过调用每个线程的start()函数让他们启动,在此之前他们不能执行。join()方法等待线程结束,或者是提供了超时;join()方法在我们需要等待线程完成的时候才有用。

(3)创建thread的实例,传递一个可调用的类实例


      这个方法中创建一个ThreadFunc类,其构造函数设定该类的函数参数,函数自身,函数名字符串。当实例化thread类对象时,调用类ThreadFunc,此时就回去调用__call__()这个方法,我们已经有要用到的参数,所以不需要将其传递给thread()的构造函数,直接调用即可。

(4)派生thread的子类,并且创建子类的实例

[python]  view plain  copy
  1. #!/usr/bin/env python3  
  2. # -*- coding: utf-8 -*-  
  3. """ 
  4. Created on Thu Jan 11 16:51:18 2018 
  5.  
  6. @author: lisir 
  7. """  
  8. import threading  
  9. from time import sleep  
  10. from time import ctime  
  11.   
  12. loops = [42]  
  13.   
  14. class MyThread(threading.Thread):  
  15.     def __init__(self, func, args, name=''):  
  16.         threading.Thread.__init__(self)  
  17.         self.name = name  
  18.         self.func = func  
  19.         self.args = args  
  20.       
  21.     def run(self):  
  22.         self.func(*self.args)  
  23.           
  24. def loop(nloop, nsec):  
  25.     print('start loop :', nloop, ' at: ', ctime())  
  26.     sleep(nsec)  
  27.     print('loop ', nloop, ' done at : ', ctime())  
  28.       
  29. def main():  
  30.     print('starting at: ', ctime())  
  31.     threads = []  
  32.     nloops = range(len(loops))  
  33.       
  34.     for i in nloops:  
  35.         t = MyThread(loop, (i, loops[i]), loop.__name__)  
  36.         threads.append(t)  
  37.     # start threads  
  38.     for i in nloops:  
  39.         threads[i].start()  
  40.     # wait for all threads to finish  
  41.     for i in nloops:  
  42.         threads[i].join()  
  43.       
  44.     print('all done at :', ctime())  
  45.       
  46. if __name__ == '__main__':  
  47.     main()  

这个方法的改写中,MyThread子类构造函数必须调用基类的构造函数,同时之前的__call__()方法变成run()。


综合以上的方法练习一个单线程和多线程执行对比程序:

首先我们吧上面的第4个方法写成一个模块myThread.py的程序,在接下来的程序中去调用

myThread.py

[python]  view plain  copy
  1. #!/usr/bin/env python3  
  2. # -*- coding: utf-8 -*-  
  3. """ 
  4. Created on Thu Jan 11 16:51:18 2018 
  5.  
  6. @author: lisir 
  7. """  
  8. # myThread.py  
  9. import threading  
  10. from time import sleep  
  11. from time import ctime  
  12.   
  13. loops = [42]  
  14.   
  15. class MyThread(threading.Thread):  
  16.     def __init__(self, func, args, name=''):  
  17.         threading.Thread.__init__(self)  
  18.         self.name = name  
  19.         self.func = func  
  20.         self.args = args  
  21.       
  22.     def getResult(self):  
  23.         return self.res  
  24.       
  25.     def run(self):  
  26.         print('starting 'self.name, ' at ', ctime())  
  27.         self.res = self.func(*self.args)  
  28.         print(self.name, ' done at ', ctime())  
  29.           
执行程序:

[python]  view plain  copy
  1. #!/usr/bin/env python3  
  2. # -*- coding: utf-8 -*-  
  3. """ 
  4. Created on Thu Jan 11 16:51:18 2018 
  5.  
  6. @author: lisir 
  7. """  
  8. from myThread import MyThread  
  9. from time import sleep  
  10. from time import ctime  
  11.           
  12. def fib(x):  
  13.     sleep(0.005)  
  14.     if x < 2:  
  15.         return 1  
  16.     return (fib(x-2) + fib(x-1))  
  17.   
  18. def fac(x):  
  19.     sleep(0.1)  
  20.     if x < 2:  
  21.         return 1  
  22.     return (x * fac(x-1))  
  23.   
  24. def sum(x):  
  25.     sleep(0.1)  
  26.     if x < 2:  
  27.         return 1  
  28.     return (x + sum(x-1))  
  29.   
  30. funcs = [fib, fac, sum]  
  31. n =12  
  32.       
  33. def main():  
  34.     nfuncs = range(len(funcs))  
  35.     print('starting at :', ctime())  
  36.     print("*********single thread***********")  
  37.     for i in nfuncs:  
  38.         print('starting ', funcs[i].__name__, 'at:',ctime())  
  39.         print(funcs[i](n))  
  40.         print(funcs[i].__name__, 'finish at :', ctime())  
  41.           
  42.     print("*********multiple thread***********")  
  43.     threads = []  
  44.     for i in nfuncs:  
  45.         t = MyThread(funcs[i], (n,), funcs[i].__name__)  
  46.         threads.append(t)  
  47.     for i in nfuncs:  
  48.         threads[i].start()  
  49.     for i in nfuncs:  
  50.         threads[i].join()  
  51.         print(threads[i].getResult())  
  52.       
  53.     print('all done at :', ctime())  
  54.       
  55. if __name__ == '__main__':  
  56.     main()  

      单线程模式下,简单的调用函数,执行函数结束就立即显示相应的结果。而多线程模式下并没有立即显示结果,在调用MyThread类后,等待所有线程都执行结束,然后去调用getResult()方法最终显示结果;这些函数的执行速度很快,因此这里加入sleep()函数减慢执行的速度。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值