python高性能编程--003--线程之Thread和threading

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python高性能编程--003--线程之Thread和threading相关的知识,希望对你有一定的参考价值。

一、线程基础
在Win32和Linux, Solaris, MacOS, BSD等大多数类Unix系统上运行时,Python支持多线程编程。Python使用POSIX兼容的线程,即pthreads。

默认情况下,源码安装的版本在2.0及以上的python;
win32的安装包中;
线程默认是打开的。

bogon:~ elaine$ python
Python 2.7.10 (default, Feb  7 2017, 00:08:15) 
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import thread
>>> 

直接在命令行下import thread,如果不报错,则说明线程支持是打开的。

如果你的Python解释器在编译时,没有打开线程支持,导入模块会失败,这种情况下,你就要重新编译你的Python解释器才能使用线程。
你可以在运行配置脚本的时候,加上“-with-thread”参数。

无线程支持的情况:
onethr.py

#!/usr/bin/python
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(2)
    print ‘loop 1 done at:‘,ctime()

def main():
    print ‘starting at:‘,ctime()
    loop0()
    loop1()
    print ‘all DONE at:‘,ctime()

if __name__ == ‘__main__‘:
    main()

输出结果:

/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 /data/study/python/project/test/onethr.py
starting at: Mon Mar 26 09:21:46 2018
start loop 0 at: Mon Mar 26 09:21:46 2018
loop 0 done at: Mon Mar 26 09:21:50 2018
start loop 1 at: Mon Mar 26 09:21:50 2018
loop 1 done at: Mon Mar 26 09:21:52 2018
all DONE at: Mon Mar 26 09:21:52 2018

Process finished with exit code 0

从上述输出结果可看出,在没有线程支持的情况下,即为在单线程中顺序执行,上述代码中有两个循环,一个循环loop0结束后,另外一个循环loop1执行,整个程序的运行时间是两个循环的运行时间的总和(6s)。
其实上述代码中的两个循环是可以同时运行的,这样整个程序的运行时间为耗时最长的循环对应的运行时间。
如loop0运行时间为4s,loop1运行时间为2s,则整个程序运行时间为4s。
为了提高程序的运行效率,python中有了多线程编程。

python有几个用于多线程编程的模块:thread,threading和Queue等。
thread模块提供了基本的线程和锁支持;
threading模块出了提供了基本的线程和锁支持,还提供了更高级别,功能更强的线程管理功能;
Queue模块是一个队列数据结构,用于实现多个进程之间数据共享。

二、thread模块
在实际项目中,不建议使用thread模块,因该模块有一个致命的缺陷:

当主线程结束时,所有的线程都会被强制结束,没有任何的告警和正常的线程清除工作,这个是没办法接受的。

模块函数:

start_new_thread()
产生一个新的线程,在新线程中用指定的参数和可选的kwargs来调用这个函数。

allocate_lock()
分配一个LockType类型的锁对象。

exit()
让线程退出。

LockType类型锁对象方法:

acquire()
尝试获取锁对象。

locked()
如果获取了锁对象则返回True,否则返回False。

release()
释放锁。

#!/usr/bin/python
from time import sleep,ctime
import thread
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(2)
    print ‘loop 1 done at:‘,ctime()

def main():
    print ‘starting at:‘,ctime()
    thread.start_new_thread(loop0,())
    thread.start_new_thread(loop1,())
    sleep(6)
    print ‘all DONE at:‘,ctime()

if __name__ == ‘__main__‘:
    main()

输出结果:

/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 /data/study/python/project/test/onethr.py
starting at: Mon Mar 26 13:10:30 2018
start loop 0 at: Mon Mar 26 13:10:30 2018
start loop 1 at: Mon Mar 26 13:10:30 2018
loop 1 done at: Mon Mar 26 13:10:32 2018
loop 0 done at: Mon Mar 26 13:10:34 2018
all DONE at: Mon Mar 26 13:10:36 2018

Process finished with exit code 0

start_new_thread(loop0,())是至少需要两个参数,一个是函数,一个是传递给函数的值。
从上述输出结果可以看出,loop0和loop1是同时运行的,即为并发执行。
在主线程中有一行代码:sleep(6)
这行代码的作用是让主线程停止下来,因为如果没有该行代码,主进程在运行了两个子线程后,主线程不会等待子线程执行完成就继续往下执行,这就会导致子线程没有执行完成,主线程直接打印输出”all DONE“,启动的两个子进程就会被动退出结束,这是不可取的。
在这段代码中,我们没有让主线程停下来等待所有子线程技术后再继续运行剩下的代码。
sleep(6)作用就是一种同步机制。

应该要有一种线程管理方法,而不是用sleep这种不靠谱的同步机制。
不让主线程过早或过晚退出,引入了锁的机制。

loops=[4,2]
def loop0(nloop,nsec,lock):
    print ‘start loop ‘,nloop,‘at:‘,ctime()
    sleep(nsec)
    print ‘loop ‘,nloop,‘done at:‘,ctime()
    lock.release()
def main():
    print ‘starting at:‘,ctime()
    locks = []
    nloops = range(len(loops))
    for i in nloops:
        lock = thread.allocate_lock()
        lock.acquire()
        locks.append(lock)
    for i in nloops:
        thread.start_new_thread(loop0,(i,loops[i],locks[i]))
        sleep(1)
    for i in nloops:
        while locks[i].locked():pass
    print ‘all DONE at:‘,ctime()

if __name__ == ‘__main__‘:
    main()

输出结果:

/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 /data/study/python/project/test/onethr.py
starting at: Mon Mar 26 13:32:09 2018
start loop  0 at: Mon Mar 26 13:32:09 2018
start loop  1 at: Mon Mar 26 13:32:10 2018
loop  1 done at: Mon Mar 26 13:32:12 2018
loop  0 done at: Mon Mar 26 13:32:13 2018
all DONE at: Mon Mar 26 13:32:13 2018

Process finished with exit code 0

三、threading模块

以上是关于python高性能编程--003--线程之Thread和threading的主要内容,如果未能解决你的问题,请参考以下文章

Python编程之算法练习_003

并发编程之多线程

多线程之ThreadLocal

(转)Python3入门之线程threading常用方法

并发编程003 --- 线程的取消与关闭

Python系列之 - multiprocessing