Python多线程节流函数测试程序卡住,请求故障排查提示
程序卡住的原因及修复方案
核心卡住原因
你在往队列添加元素后立刻调用q.join(),但此时处理队列任务的线程还没启动。queue.Queue.join()会阻塞主线程,直到队列中所有任务都被调用task_done()标记完成。但没有线程去处理队列里的元素,主线程会一直卡在q.join()这里,后续创建线程的代码根本没机会执行,所以只输出了「Creating Queue, 20」就卡住。
其他潜在问题
- 缺少
task_done()调用:就算线程启动了,每次q.get()取出任务后,没有调用q.task_done(),q.join()永远不会结束。 - 全局变量线程不安全:
lastcalled和logstring是全局变量,多线程同时读写会导致竞态条件——比如多个线程同时读取lastcalled,判断间隔后同时更新,会突破节流限制;logstring的字符串拼接也可能出现乱序或内容丢失。 - 节流逻辑不严谨:当前的节流逻辑只是在调用后sleep,没有确保两次调用的间隔至少是
g_throttle_interval,多线程下会失效。
修复后的代码
import time from threading import Thread, Lock import queue # 用锁保护全局变量的线程安全 lock = Lock() lastcalled = 0.000000999 logstring = "" g_throttle_interval = 0.5 # seconds maxQitems = 20 q = queue.Queue(maxQitems) class OnlyForStaticMethod: @staticmethod def ThrottledMethod(inputx): global lastcalled, logstring try: with lock: currtime = time.time() # 确保两次调用间隔至少达到节流时间 wait_time = g_throttle_interval - (currtime - lastcalled) if wait_time > 0: time.sleep(wait_time) # 更新日志和最后调用时间 log_entry = f"\n{inputx} , Lastcalled, {lastcalled}, and now, {currtime}" logstring += log_entry lastcalled = time.time() except Exception as e: print("Error1 , ", repr(e)) return 1 def CalledByThread(): while True: try: item = q.get() OnlyForStaticMethod.ThrottledMethod(item) q.task_done() # 标记任务完成,让q.join()能结束 except Exception as e: print("Error2 , ", repr(e)) return 1 print("Creating Queue, ", maxQitems) try: for x in range(20): q.put(x) print("Creating threads") # 先启动线程,再调用q.join()等待任务完成 for i in range(10): t = Thread(target=CalledByThread) t.daemon = True t.start() q.join() # 等待所有队列任务处理完成 except Exception as e: print("Some exception here ", repr(e)) import sys sys.exit(1) print("\n *** \n Program Over, log below \n") print(logstring)
关键修改点
- 调整
q.join()的位置:先启动所有处理线程,再调用q.join()等待任务完成。 - 添加
q.task_done():每次处理完队列元素后,调用该方法标记任务完成,让q.join()能正常结束。 - 添加线程锁
Lock():用with lock:包裹对lastcalled和logstring的读写操作,保证线程安全,避免竞态条件。 - 优化节流逻辑:计算需要等待的时间,确保两次API调用的间隔至少是
g_throttle_interval,而不是简单的调用后sleep。
内容的提问来源于stack exchange,提问作者vikramagain
相关产品推荐
相关产品推荐

