Python多线程创建与终止机制详解:Threading模块实战
本文深入解析Python中threading模块的使用,涵盖通过Target参数和继承Thread类两种方式创建线程。重点探讨线程终止策略,对比setDaemon()与Event机制的差异,指出setDaemon可能导致资源未释放的风险,并推荐通过Event机制安全终止子线程,附带完整代码示例与执行结果分析。
Python主要依赖thread和threading这两个模块来实现多线程功能。
Python中的thread模块属于底层实现,而threading模块则在此基础上进行了封装,使得使用更加便捷。然而,由于CPython解释器中存在全局解释器锁(GIL),threading模块无法充分利用多核CPU的计算能力。若需充分发挥多核性能,建议使用multiprocessing模块(但在Windows环境下使用该模块可能会遇到若干兼容性问题)。
如果对线程应用有更高性能要求,可以考虑使用Stackless Python。Stackless Python是Python的一个修改版本,对多线程编程提供了更好的支持,特别是引入了对微线程(microthreads)的支持。微线程是一种轻量级线程,其在多个线程间切换时消耗的时间相对较少,且占用的系统资源也更少。
通过threading模块创建新线程主要有两种方法:第一种是向Thread对象传递一个可执行方法(或对象),即使用threading.Thread(Target=executable Method);第二种是继承threading.Thread类定义子类并重写run()方法。在第二种方法中,唯一必须重写的方法是run(),可以根据需要决定是否重写__init__()方法。需要注意的是,如果重写了__init__(),必须在函数第一行调用父类的__init__(),否则将触发错误“AssertionError: Thread.__init__() not called”。
Python的threading模块与其他语言不同之处在于,它没有提供直接终止线程的方法。通过Python threading.Thread()启动的线程彼此是独立的。例如,若在线程A中启动了线程B,那么A和B是彼此独立执行的线程。若想终止线程A的同时强力终止线程B,一种简单的方法是在线程A中调用B.setDaemon(True)。
然而,这样做带来的问题是:线程B中的资源(如打开的文件、传输的数据等)可能无法正确释放。因此,setDaemon()并不是一个理想的方法,更为妥当的方式是通过Event机制来实现。以下程序展示了使用setDaemon()和Event机制终止子线程的区别。
import threading
import time
class mythread(threading.Thread):
def __init__(self,stopevt = None,File=None,name = 'subthread',Type ='event'):
threading.Thread.__init__(self)
self.stopevt = stopevt
self.name = name
self.File = File
self.Type = Type
def Eventrun(self):
while not self.stopevt.isSet():
print self.name +' alive\n'
time.sleep(2)
if self.File:
print 'close opened file in '+self.name+'\n'
self.File.close()
print self.name +' stoped\n'
def Daemonrun(self):
D = mythreadDaemon(self.File)
D.setDaemon(True)
while not self.stopevt.isSet():
print self.name +' alive\n'
time.sleep(2)
print self.name +' stoped\n'
def run(self):
if self.Type == 'event': self.Eventrun()
else: self.Daemonrun()
class mythreadDaemon(threading.Thread):
def __init__(self,File=None,name = 'Daemonthread'):
threading.Thread.__init__(self)
self.name = name
self.File = File
def run(self):
while True:
print self.name +' alive\n'
time.sleep(2)
if self.File:
print 'close opened file in '+self.name+'\n'
self.File.close()
print self.name +' stoped\n'
def evtstop():
stopevt = threading.Event()
FileA = open('testA.txt','w')
FileB = open('testB.txt','w')
A = mythread(stopevt,FileA,'subthreadA')
B = mythread(stopevt,FileB,'subthreadB')
print repr(threading.currentThread())+'alive\n'
print FileA.name + ' closed?
'+repr(FileA.closed)+'\n'
print FileB.name + ' closed? '+repr(FileB.closed)+'\n'
A.start()
B.start()
time.sleep(1)
print repr(threading.currentThread())+'send stop signal\n'
stopevt.set()
A.join()
B.join()
print repr(threading.currentThread())+'stoped\n'
print 'after A stoped, '+FileA.name + ' closed? '+repr(FileA.closed)+'\n'
print 'after A stoped, '+FileB.name + ' closed?
'+repr(FileB.closed)+'\n'
def daemonstop():
stopevt = threading.Event()
FileA = open('testA.txt','r')
A = mythread(stopevt,FileA,'subthreadA',Type = 'Daemon')
print repr(threading.currentThread())+'alive\n'
print FileA.name + ' closed?
'+repr(FileA.closed)+'\n'
A.start()
time.sleep(1)
stopevt.set()
A.join()
print repr(threading.currentThread())+'stoped\n'
print 'after A stoped, '+FileA.name + ' closed? '+repr(FileA.closed)+'\n'
if not FileA.closed:
print 'You see the differents, the resource in subthread may not released with setDaemon()'
FileA.close()
if __name__ =='__main__':
print '-------stop subthread example with Event:----------\n'
evtstop()
print '-------Daemon stop subthread example :----------\n'
daemonstop()
执行结果如下:
-------stop subthread example with Event:---------- <_MainThread(MainThread, started 2436)>alive testA.txt closed? False testB.txt closed? False subthreadA alive subthreadB alive <_MainThread(MainThread, started 2436)>send stop signal close opened file in subthreadA close opened file in subthreadB subthreadA stoped subthreadB stoped <_MainThread(MainThread, started 2436)>stoped after A stoped, testA.txt closed? True after A stoped, testB.txt closed? True -------Daemon stop subthread example :---------- <_MainThread(MainThread, started 2436)>alive testA.txt closed? False subthreadA alive subthreadA stoped <_MainThread(MainThread, started 2436)>stoped after A stoped, testA.txt closed? False You see the differents, the resource in subthread may not released with setDaemon()
总结
以上就是本文关于Python线程创建与终止实例代码的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









