Queue结合线程sleep实现安全计数,核心是用线程安全队列作生产者-消费者中转站,通过sleep模拟真实延迟、控制产出节奏,避免竞态与资源抢占,并需配合task_done()和join()确保任务完成。

用 Queue 结合线程的 sleep 实现计数,核心是让多个线程协作往队列里“安全地”塞数字,同时控制节奏——sleep 不是用来精确计时的,而是模拟真实场景中的延迟(比如网络响应、I/O等待),顺便避免线程疯狂轮询或抢占资源。
理解 Queue 的作用:线程安全的计数中转站
queue.Queue 是 Python 内置的线程安全队列,不用手动加锁就能在多线程间安全传递数据。在计数练习中,它常用来:
- 让工作线程把生成的数字(如 1, 2, 3…)放进队列
- 让另一个线程(比如主线程或专门的收集线程)从队列取数并打印/累加
- 天然实现生产者-消费者解耦,避免竞态条件
用 sleep 控制生产节奏,避免“一口气全塞完”
如果不加 sleep,线程可能瞬间把全部数字入队,失去“并发感”。加 time.sleep(0.1) 这类小延迟,能让线程逐个产出,更贴近实际场景。注意:
– 不要睡太久(比如 5 秒),否则练习变卡顿;
– 睡的时间不必精确,重点是制造可观察的异步效果。
示例片段(两个生产者线程,一个消费者):
import threading
import queue
import time
<p>q = queue.Queue()</p><p>def producer(name, start, count):
for i in range(start, start + count):
q.put(i)
print(f"[{name}] 放入 {i}")
time.sleep(0.2) # 每放一个,停 0.2 秒</p><p>def consumer():
while True:
try:
num = q.get(timeout=1) # 等待 1 秒,没数据就检查是否该停
print(f"→ 消费: {num}")
q.task_done()
except queue.Empty:
break # 队列空且无新数据,退出</p><h1>启动两个生产者</h1><p>t1 = threading.Thread(target=producer, args=("A", 1, 3))
t2 = threading.Thread(target=producer, args=("B", 10, 3))
t3 = threading.Thread(target=consumer)</p><p>t1.start(); t2.start(); t3.start()
t1.join(); t2.join()
q.join() # 等待所有任务被消费完
t3.join()关键细节:别漏掉 task_done 和 join
如果要用 q.join() 等待所有任务完成,必须配合 q.task_done()。否则主线程会永远卡住。常见错误:
- 只调
q.get()却忘了q.task_done() - 消费者异常退出,导致部分任务没标记完成
- 误用
q.empty()判断队列是否结束(不靠谱,因线程间有延迟)
进阶小技巧:用计数器替代纯打印,做真正“计数”
如果目标是统计总数(比如累计到 100),可在消费者里加一个共享变量(记得加锁)或直接用 queue.Queue 做“结果队列”:
- 每个生产者最后往另一个
result_q里放自己产了多少个 - 主线程从
result_q取值并求和 - 或者用
threading.local()给每个线程配独立计数器,最后汇总
这样就把“放数”和“计数”逻辑分开了,结构更清晰,也更适合扩展。

















