Python多线程创建与终止机制详解:Threading模块实战

陈默
陈默
发布时间:2026-10-13| 3人浏览过
原创

本文深入解析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线程创建与终止实例代码的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。