Python多线程线程未销毁:未join导致内存占用上涨
线程未正常销毁的可能原因及解决方案
1. Streamlit缓存引发的资源残留
你的get_links函数使用了@st.cache_data装饰器,这个装饰器会缓存函数返回值,同时可能保留函数执行过程中关联的资源引用,导致线程相关对象无法被垃圾回收。再加上Streamlit的热重载机制,脚本会反复执行,缓存的资源会持续累积,进一步加重内存占用问题。
解决方法:
- 如果
get_links不需要缓存,直接移除@st.cache_data装饰器; - 若必须缓存,确保返回值不含未释放的资源(如driver实例),同时设置缓存过期时间自动清理,比如:
@st.cache_data(show_spinner=False, ttl=3600) def get_links(i, resumeContent): # 业务逻辑
2. Chrome浏览器进程未彻底终止
虽然你调用了driver.close()和driver.quit(),但ChromeDriver偶尔会出现进程残留:
- 异常可能发生在清理代码执行前,导致
quit()未被触发; - ChromeDriver本身的bug,导致调用
quit()后仍有浏览器子进程存活。
解决方法:
- 改用
try...finally确保无论是否异常,都执行driver清理,同时手动强制结束Chrome相关进程:def get_links(i, resumeContent): driver = None try: # 初始化driver及业务逻辑 with webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options) as driver: # 获取链接等操作 except Exception as e: print(f"线程执行出错: {str(e)}") finally: # 强制清理Chrome进程 import os if os.name == 'nt': os.system("taskkill /f /im chromedriver.exe") os.system("taskkill /f /im chrome.exe") else: os.system("pkill chromedriver") os.system("pkill chrome") - 不要混用
with语句和手动close()/quit(),with本身会自动调用quit(),重复调用可能引发异常。
3. 全局变量Final_Array持续累积
Final_Array作为全局列表,每次脚本运行(尤其是Streamlit热重载)不会自动重置,会持续追加数据,导致内存占用上升。同时列表中的元素可能持有线程相关对象,阻碍垃圾回收。
解决方法:
- 将
Final_Array改为函数内局部变量,或在每次创建线程前手动清空:# 创建线程前清空列表 Final_Array.clear() threads = [] for i in links: # 创建并启动线程 - 多线程写入列表必须加锁,避免数据竞争和状态异常:
import threading lock = threading.Lock() # 在append操作时加锁 with lock: Final_Array.append((something1, something2, something3, something4, something5, something6, something7))
4. 线程编号递增的说明
Python的线程编号是全局递增的,即使旧线程已销毁,新线程的编号也会延续之前的数字,这是正常机制,不代表旧线程未销毁。真正需要关注的是内存占用和进程残留问题,而非线程编号。
内容的提问来源于stack exchange,提问作者alex
相关产品推荐
相关产品推荐

