利用队列来做同步时是非常简单方便的。
1. 简介
queue模块提供了同步的线程安全的队列类,都具有原子性,实现线程间的同步。
Queue: FIFO; LifoQueue: LIFO; PriorityQueue (优先级队列)
task_done(): 在使用join()的时候,当queue中所有的项目都被取出,且每个项目取出后都使用了task_done(),那么就可以释放join()阻塞。
用于消费者,每次get()以后,使用task_done() 是告诉队列正在处理的get任务完成,如果join()当前处于阻塞状态,那么当处理完所有项时它将继续运行(这意味着对于已经放入队列的每个项都接收到task_done()调用)。
如果调用的次数超过在队列中放置的项的次数,则引发ValueError错误。
如果不需要join()的时候也可以不使用task_done()
2. 代码实现
2.1 导包
import queue
import threading
import time
import random
que = queue.Queue(10)
2.2 生产者
def produce():
name = threading.current_thread().getName()
print(name + "线程启动......")
for i in range(5):
# num = random.randint(1, 100)
num = i
que.put(num)
print("生产者生产出数据:", num)
time.sleep(0.2)
print("生产结束!")
2.3 消费者
def consume():
name = threading.current_thread().getName()
time.sleep(1)
print(name + "线程启动......")
while not que.empty():
print(name + "检测到队列数量: ", que.qsize())
time.sleep(0.3)
item = que.get()
print(name, "取出: ", item)
que.task_done()
print("消费者结束!")
2.4 测试
# 启动了1个生产者线程,2个消费者线程
p = threading.Thread(target=produce, name='生产者')
c1 = threading.Thread(target=consume, name='消费者1')
c2 = threading.Thread(target=consume, name="消费者2")
p.start()
c1.start()
c2.start()
que.join()
print("over")