threading.join()未等待线程结束?Python2.7多线程控制疑问
解决Python线程并发控制问题:同时仅运行2个线程(及子进程)
你遇到的问题其实有两个核心关键点,先帮你拆解清楚:
1. 你对join()的理解没错,但线程本身没“持续运行”
join()确实会让主线程等待子线程结束后再继续执行,但你的func1里用了subprocess.Popen()——这个函数启动子进程后会立刻返回,不会等待do.py执行完毕。所以你的线程启动后,几毫秒内就执行完func1并结束了,join()自然也瞬间完成,导致下一轮循环立刻启动新线程,进而疯狂创建do.py子进程,最终电脑负载拉满。
2. 你的代码还有个致命bug:无限循环
看你的while j <= B循环,里面完全没有j += 1的逻辑!这会导致j永远停在初始值,无限创建线程和子进程,这绝对是负载过高的核心原因之一,先把这个bug修了!
解决方案
方案一:修改func1,让线程等待子进程结束,再手动控制并发
先让线程和do.py子进程的生命周期绑定,再用join()控制每次只运行2个线程:
import threading import subprocess def func1(string): # 启动子进程并等待它执行完毕 proc = subprocess.Popen(string, shell=True) proc.wait() A = 10 # 替换成你的实际A值 B = 5 # 替换成你的实际B值 for i in range(0, A): j = 0 while j <= B: tl = [] # 创建并启动第一个线程 cmd = 'python do.py {} {} {}'.format(i, j, 3) t = threading.Thread(target=func1, args=[cmd]) t.start() tl.append(t) # 创建并启动第二个线程 cmd = 'python do.py {} {} {}'.format(i, j, 3) t = threading.Thread(target=func1, args=[cmd]) t.start() tl.append(t) # 等待这两个线程(及对应的do.py进程)结束 for t in tl: t.join() j += 1 # 必须递增j,避免无限循环!
方案二:用线程池更优雅地控制并发(推荐)
Python 2.7可以用multiprocessing.dummy.ThreadPool(基于线程的池),它会自动帮你管理线程数量,不用手动维护线程列表和join():
from multiprocessing.dummy import ThreadPool import subprocess def func1(string): proc = subprocess.Popen(string, shell=True) proc.wait() A = 10 B = 5 # 生成所有要执行的命令列表 commands = [] for i in range(0, A): j = 0 while j <= B: # 这里注意:你原来的代码重复添加了两次完全相同的命令,是笔误的话可以删掉一个 cmd = 'python do.py {} {} {}'.format(i, j, 3) commands.append(cmd) cmd = 'python do.py {} {} {}'.format(i, j, 3) commands.append(cmd) j += 1 # 创建最多同时运行2个线程的线程池 pool = ThreadPool(2) # 批量执行所有命令,自动控制并发数 pool.map(func1, commands) # 关闭池并等待所有任务完成 pool.close() pool.join()
这样就能严格保证同一时间最多有2个do.py进程在运行,不会让电脑负载过高。
内容的提问来源于stack exchange,提问作者meleke
相关产品推荐
相关产品推荐

