使用threading库及Semaphore仍遇RuntimeError: Can't start new thread问题
我之前踩过一模一样的坑!你说的完全没错——threading.Semaphore(4)只能控制同时运行的线程数量,但如果你一次性把1000个Thread对象都创建出来并调用start(),系统的线程资源还是会被瞬间耗尽,毕竟Semaphore只是让后面的线程等着,可线程本身已经被创建出来了,这才是报错的根源。
给你两个靠谱的解决方案:
方案一:用线程池(最推荐)
Python的concurrent.futures.ThreadPoolExecutor是专门用来处理这种场景的,它会帮你自动管理线程的创建、复用和销毁,不会一次性创建所有线程。比如设置max_workers=4,系统里最多只会存在4个线程,任务会被放到内部队列,线程空闲了就去取新任务执行。
举个实际的代码例子:
from concurrent.futures import ThreadPoolExecutor def process_task(task): # 这里写你的任务处理逻辑,比如: print(f"Processing task {task}") if __name__ == "__main__": # 1000个任务也完全没问题 task_list = range(0, 1000) # 初始化线程池,最多4个并发线程 with ThreadPoolExecutor(max_workers=4) as executor: # 把任务映射到线程池执行 executor.map(process_task, task_list)
这种写法不仅简洁,还能避免手动管理线程的麻烦,完全解决线程数量过载的问题。
方案二:手动用队列控制线程创建(如果坚持用threading模块)
如果你不想用线程池,也可以手动实现“固定数量线程+任务队列”的模式:只创建4个工作线程,让它们从队列里不断取任务执行,直到所有任务处理完毕。这样系统里始终只有4个线程,不会出现创建1000个线程的情况。
代码示例:
import threading from queue import Queue def worker_thread(task_queue): while True: # 从队列取任务,取不到就阻塞 task = task_queue.get() # 用None作为终止信号,收到就退出线程 if task is None: break # 执行任务逻辑 process_task(task) # 告诉队列这个任务处理完了 task_queue.task_done() def process_task(task): print(f"Processing task {task}") if __name__ == "__main__": task_queue = Queue() max_workers = 4 # 把所有任务放到队列里 for task in range(0, 1000): task_queue.put(task) # 创建并启动4个工作线程 threads = [] for _ in range(max_workers): t = threading.Thread(target=worker_thread, args=(task_queue,)) t.start() threads.append(t) # 等待队列里所有任务都处理完 task_queue.join() # 给每个线程发终止信号 for _ in range(max_workers): task_queue.put(None) # 等待所有线程结束 for t in threads: t.join()
再补充下为什么之前的Semaphore没用
你之前的写法应该是循环创建1000个Thread,然后每个线程里先semaphore.acquire(),执行任务后再release()。这种情况下,1000个线程其实都已经被创建并启动了,只是大部分在阻塞等待Semaphore的许可,系统的线程数量还是1000,远超系统能承载的上限(一般系统默认的线程数上限在几百左右),所以才会抛出Can't start new thread的错误。
内容的提问来源于stack exchange,提问作者jo2083248

