Python线程队列存入重复项问题:短时间入队不同数据却出现重复的解决方案求助
解决Worker线程队列中数据重复的问题
我一眼就看出问题出在哪了——你入队的是同一个self.peopleTick字典对象的引用,而不是每次都传入新的独立副本。
问题根源解释
当你在短时间内连续调用self.dbWriter.put((['insertTick', self.peopleTick],))时,你只是把指向同一个字典的引用反复放进队列里。如果在入队后你又修改了self.peopleTick的内容(比如更新最新的tick数据),队列里所有指向这个对象的引用都会“同步”看到最新修改,导致你取出时看起来全是同一个副本。time.sleep(2)能临时“解决”,只是因为这段时间里程序修改self.peopleTick的节奏变慢了,但这根本不是真正的解决方案。
具体修复方案
方案1:入队时创建字典的独立副本
每次调用put的时候,不要直接传入self.peopleTick,而是传入它的拷贝(根据字典结构选择浅拷贝或深拷贝):
# 如果字典没有嵌套结构,浅拷贝足够 self.db_writer.put((['insertTick', self.peopleTick.copy()],)) # 如果字典有嵌套的子字典/列表,用深拷贝 import copy self.db_writer.put((['insertTick', copy.deepcopy(self.peopleTick)],))
这样每次入队的都是全新的字典对象,后续修改self.peopleTick不会影响已经入队的内容。
方案2:改用不可变对象传递数据
从根源上避免引用共享问题,把self.peopleTick改成不可变类型(比如dataclass或namedtuple),一旦创建就无法修改:
from dataclasses import dataclass @dataclass(frozen=True) class TickData: symbol: str price: float # 添加你需要的其他字段 # 更新tick数据时,创建新对象而非修改旧对象 self.peopleTick = TickData(symbol="BTCUSDT", price=42000.5) self.db_writer.put((['insertTick', self.peopleTick],))
每次入队的都是全新的不可变对象,自然不会出现引用共享导致的重复问题。
额外的线程安全小优化
你的Worker线程批量取队列的逻辑可以稍作调整,让代码更简洁且线程安全:
def run(self): db_conn = None while True: statements = [] # 阻塞等待第一个元素 stmt = self.q.get() if stmt is None: self.q.task_done() return statements.append(stmt) # 批量取剩余非阻塞元素 while True: try: stmt = self.q.get(block=False) if stmt is None: statements.append(stmt) break statements.append(stmt) except queue.Empty: break # 后续的数据库操作逻辑保持不变...
内容的提问来源于stack exchange,提问作者RavenMan
相关产品推荐
相关产品推荐

