使用队列(queue)控制线程通信
对于queue模块,可以参考:https://blog.csdn.net/weixin_44013214/article/details/103348877
本文主要使用queue模块中的Queue来控制线程通信
简单说明:
queue.Queue类的使用:
queue.Queue(maxsize=0):代表FIFO(先进先出)的队列
- 参数说明:maxisize—队列的大小
- 当maxsize等于0或者负数时,表示该队列的大小是无限制的
包含的属性和方法:
- Queue.qsize():返回队列中的实际大小,即队列中包含有多少个元素
- Queue.empty():判断队列是否为空
- Queue.full():判断队列是否已满
- Queue.put(item, block=True, timeout=None):向队列中放入元素,当block为True时,如果队列已满,再次放入元素,则当前的线程就会被阻塞;参数timeout:表示线程阻塞的时间,将其设为None,则表示一直阻塞,直到队列中的元素有被取出。
- Queue.get(block=True, timeout=None):向队列中取出元素,当block为True时,如果队列为空,再次取出元素,则当前的线程就会被阻塞;参数timeout:表示线程阻塞的时间,将其设为None,则表示一直阻塞,知道队列的元素有被放入。
- Queue.putnow(item):向队列放入元素,不阻塞,相当于put()方法中的block设为Flase
- Queue.getnow():向队列取出元素,不阻塞,相当于put()方法中的block设为Flase
简单的例子:
import queue
# 定义一个长度大小为2的队列bq1
bq1 = queue.Queue(maxsize=2)
# 向队列bq放入两个元素 python 和java
bq1.put('python')
bq1.put('java')
# 此时队列已满,在使用put()方法放入元素,则会导致线程阻塞
# bq.put('java')
# 取出bq1中的元素
bq1.get()
bq1.get()
# 此时队列bq1为空 ,再次去除元素会导致线程阻塞
# bq1.get()
以上就是queue.Queue队列阻塞的特性,queue中其他的队列阻塞与其相似
利用queue.Queue实现线程通信
例子:
import queue
import time
import threading
# 生产者
def product(bq):
str_tuple = ('Python', 'Java', 'Ruby')
for i in range(9999):
# 打印出当前的线程
print(threading.current_thread().name + '生产者开始生产元组元素')
time.sleep(0.2)
# 向队列中放入元素,如果队列已满,则会导致现程阻塞
bq.put(str_tuple[i % 3])
print(threading.current_thread().name + '生产者生产元素完成!')
# 消费者
def consume(bp):
while True:
print(threading.current_thread().name + '消费者开始消费元组元素')
time.sleep(0.2)
# 从队列中取出元素,如果队列为空,则会导致线程阻塞
t = bp.get()
print(threading.current_thread().name + f'消费者消费元组元素[{ t }]完成!')
# 创建一个容量为1 的队列
bq = queue.Queue(maxsize=1)
# 开启三个生产者线程
threading.Thread(target=product, args=(bq, ), name='生产者A').start()
threading.Thread(target=product, args=(bq, ), name='生产者B').start()
threading.Thread(target=product, args=(bq, ), name='生产者C').start()
# 开启一个消费者线程
threading.Thread(target=consume, args=(bq, ), name='消费者A').start()
运行结果:
总结:
使用队列来控制线程通信,其实就是利用了队列在已满或者已空的情况下,put()或者get()方法的再次操作会导致线程阻塞的来实现的,同时可以利用队列的不同取出顺序(FIFO,LIFO等)来实现不同线程的先后使用。