生产者-消费者问题与python Queue模块
生产者-消费者模型是一个典型的场景,在这个场景下,商品或服务的生产者生产商品,然后将其放到类似队列的数据结构中。生产商品的时间是不确定的,同样消费者消费生产者的商品的时间也是不确定的。
下面我们用Queue模块编写一个演示程序,帮助理解。
典型的应用比如说下载软件多线程下载的时候,可以通过队列来分配任务,设置任务的优先顺序等。但是这里就先借用书上的例子了。
import random
import time
from queue import Queue
import threading
def writeQ(queue):
print('producing object for Q...')
# put(item,block=True,timeout=None)
# 默认block为True,block为True,timeout=None就表示,在遇到可用空间之前会阻塞
queue.put('xxx',1)
# queue.qsize() 获取当前队列大小,由于返回时队列大小可能被其他线程修改,所以该值为近似值
print("producer ,size now",queue.qsize())
def readQ(queue):
val = queue.get(1)
print('consumed object from Q... size now',queue.qsize())
def writer(queue,loops):
for i in range(loops):
writeQ(queue)
time.sleep(random.randint(1,3))
def reader(queue,loops):
for i in range(loops):
readQ(queue)
time.sleep(random.randint(2,5))
funcs = [writer,reader]
# 书上很多骚操作,这一步实际上生成了[0,1]
nfuncs=range(len(funcs))
def main():
nloops = random.randint(2,5)
q=Queue(32)
threads=[]
for i in nfuncs:
t=threading.Thread(target=funcs[i],args=(q,nloops))
threads.append(t)
for t in threads:
t.start()
for t in threads:
t.join()
print('all DONE')
if __name__=='__main__':
main()
producing object for Q...
producer ,size now 1
consumed object from Q... size now 0
producing object for Q...
producer ,size now 1
producing object for Q...
producer ,size now 2
consumed object from Q... size now 1
producing object for Q...
producer ,size now 2
consumed object from Q... size now 1
producing object for Q...
producer ,size now 2
consumed object from Q... size now 1
consumed object from Q... size now 0
all DONE
编写这种并发的程序还是go语言方便啊,队列和多线程类似的东西都是语言内置语法,简单,代码量很少。性能也会高得多
网友评论