多线程相比单线程,有什么优劣势呢?
1)多线程并发优点:在执行IO密集型任务时,某个任务阻塞的时候CPU会切换到其他任务就大大提高了CPU的使用效率。
2)多线程并发缺点:在执行计算密集型任务时,CPU一直在计算没有休息。因此python多线程并发并不能显著提高效率,但是使用多进程执行效率有所提升。
简单的说,多线程是充分利用硬件资源,提高并发数,但也不是开启的越多越好,在单核或者密集型计算任务时,多线程并不占多大优势。
thread
下面举例:
使用单线程执行:
# -*- coding: utf-8 -*- import thread from time import sleep,ctime import random def loop0(n): print 'start loop 0 :',ctime() sleep(n) print 'end loop 0 :',ctime() def loop1(n): print 'start loop 1 :',ctime() sleep(n) print 'end loop 1 :',ctime() def loop2(n): print 'start loop 2 :',ctime() sleep(n) print 'end loop 2 :',ctime() def main(): loop0(1) loop1(2) loop2(3) if __name__ == "__main__": print '--------------start main :', ctime() main() print '---------------end main :', ctime()
执行结果,花费了6秒:
--------------start main : Fri May 29 17:41:25 2020 start loop 0 : Fri May 29 17:41:25 2020 end loop 0 : Fri May 29 17:41:26 2020 start loop 1 : Fri May 29 17:41:26 2020 end loop 1 : Fri May 29 17:41:28 2020 start loop 2 : Fri May 29 17:41:28 2020 end loop 2 : Fri May 29 17:41:31 2020 ---------------end main : Fri May 29 17:41:31 2020
使用多线程执行:
# -*- coding: utf-8 -*- import thread from time import sleep,ctime def loop0(n): print 'start loop 0 :',ctime() sleep(n) print 'end loop 0 :',ctime() def loop1(n): print 'start loop 1 :',ctime() sleep(n) print 'end loop 1 :',ctime() def loop2(n): print 'start loop 2 :',ctime() sleep(n) print 'end loop 2 :',ctime() def main(): try: thread.start_new_thread(loop0, (1,)) #派生一个新的线程,传入方法名和参数 thread.start_new_thread(loop1, (3,)) thread.start_new_thread(loop2, (2,)) return True except Exception as e: print e return False if __name__ == "__main__": print '--------------start main :', ctime() main() sleep(7) #此方法,是保证子线程完成后,主线程才退出 print '---------------end main :', ctime()
执行结果,只花费了3秒:
--------------start main : Fri May 29 17:44:54 2020 start loop 0 :start loop 1 : start loop 2 : Fri May 29 17:44:54 2020 Fri May 29 17:44:54 2020 Fri May 29 17:44:54 2020 end loop 0 : Fri May 29 17:44:55 2020 end loop 2 : Fri May 29 17:44:56 2020 end loop 1 : Fri May 29 17:44:57 2020 ---------------end main : Fri May 29 17:45:01 2020
以上对比,可以发现,使用多线程后,loop三个方法是同时开始,最后结束只花费了最长方法的3秒,大大提高了并发数。
但是我们发现,thread.start_new_thread(),在执行的时候,会报错:
Unhandled exception in thread started by sys.excepthook is missing lost sys.stderr Unhandled exception in thread started by sys.excepthook is missing lost sys.stderr
这是因为子线程还没执行完,主线程就退出了,子线程执行完后发现老大走了,大喊一声:卧槽,人呢? 然后索性也就地卧倒了(异常退出),哈哈…
所以在执行的时候加上sleep(7) 、while(1)pass维持主线程,或者给每一个子线程加上一个锁,当所有锁都释放的时候再结束主线程,这里就不扩展了。
threading
接下来介绍threading,threading是thread的升级版,threading提供的是更高级的完全的线程管理。
低级别的thread模块是推荐给高手用,一般应用程序推荐使用更高级的threading模块:
1.它更先进,有完善的线程管理支持,此外,在thread模块的一些属性会和threading模块的这些属性冲突。
2.thread模块有很少的(实际上是一个)同步原语,而threading却有很多。
3.thread模块没有很好的控制主线程和子线程的关系,而threading会允许默认,重要的子线程完成后再退出。
举例:
# -*- coding: utf-8 -*- import threading from time import sleep,ctime def loop0(n): print 'start loop 0 :',ctime() sleep(n) print 'end loop 0 :',ctime() def loop1(n): print 'start loop 1 :',ctime() sleep(n) print 'end loop 1 :',ctime() def loop2(n): print 'start loop 2 :',ctime() sleep(n) print 'end loop 2 :',ctime() def main(): try: th = threading.Thread(target=loop0, args=(1,)) th.start() th2 = threading.Thread(target=loop1, args=(2,)) th2.start() th3 = threading.Thread(target=loop2, args=(3,)) th3.start() return True except Exception as e: raise e if __name__ == "__main__": print '--------------start main :', ctime() main() print '---------------end main :', ctime()
执行结果:
--------------start main : Fri May 29 18:48:24 2020 start loop 0 : Fri May 29 18:48:24 2020 start loop 1 : Fri May 29 18:48:24 2020 ---------------end main :start loop 2 : Fri May 29 18:48:24 2020Fri May 29 18:48:24 2020 end loop 0 : Fri May 29 18:48:25 2020 end loop 1 : Fri May 29 18:48:26 2020 end loop 2 : Fri May 29 18:48:27 2020
可以看到,执行时间还是3秒,但是不需要额外维持主线程的运行,子线程一样可以完成。
threading常用方法:
run() 如果采用方法2创建线程就需要重写该方法 getName() 获得线程的名称(方法2中有示例) setName() 设置线程的名称 start() 启动线程 join(timeout) 在join()位置等待另一线程结束后再继续运行join()后的操作,timeout是可选项,表示最大等待时间 setDaemon(bool) True:当父线程结束时,子线程立即结束;False:父线程等待子线程结束后才结束。默认为False isDaemon() 判断子线程是否和父线程一起结束,即setDaemon()设置的值 isAlive() 判断线程是否在运行
至此,thread和threding多线程的使用介绍完毕。
转载请注明:永盟博客 » python多线程的使用(thread和threading)