首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Python的Socket知识7:队列、生产者消费者模型

1、队列

队列是一种数据结构,队列queue 多应用在多线程应用中,多线程访问共享变量。对于多线程而言,访问共享变量时,队列queue是线程安全的。从queue队列的具体实现中,可以看出queue使用了1个线程互斥锁(pthread.Lock()),以及3个条件标量(pthread.condition()),来保证了线程安全。

主要的队列类型:

先进先出(First in First Out)。Queue.Queue()

后进先出(Last in First Out)。Queue.LifoQueue()

优先级队列Queue.PriorityQueue()

双向队列Queue.deque()

基本方法:

1)创建一个“队列”对象

import Queue

q = Queue.Queue(maxsize = 10)

Queue.Queue类即是一个队列的同步实现。队列长度可为无限或者有限。可通过Queue的构造函数的可选参数maxsize来设定队列长度。如果maxsize小于1就表示队列长度无限。

2)将一个值放入队列中

q.put(10,block=False,timeout=2)

调用队列对象的put()方法在队尾插入一个项目。put()有三个参数,第一个item为必需的,为插入项目的值;第二个block为可选参数,默认为1,表示阻塞。还有一个超时时间。如果队列当前为空且block为1,put()方法就使调用线程暂停,直到空出一个数据单元。如果block为0,put方法将引发Full异常。

3)将一个值从队列中取出

q.get()

调用队列对象的get()方法从队头删除并返回一个项目。可选参数为block,默认为True,表示阻塞。如果队列为空且block为True,get()就使调用线程暂停,直至有项目可用。如果队列为空且block为False,队列将引发Empty异常。timeout为阻塞时的超时时间

其他常用方法:

Queue.qsize() 返回队列的大小,队列里面真实的个数

Queue.maxsize,返回队列的最大可容纳元素数

Queue.empty() 如果队列为空,返回True,反之False

Queue.full() 如果队列满了,返回True,反之False

Queue.full 与 maxsize 大小对应

Queue.get_nowait() 相当Queue.get(False)

非阻塞 Queue.put(item) 写入队列,timeout等待时间

Queue.put_nowait(item) 相当Queue.put(item, False)

Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号

Queue.join()阻塞调用线程,直到队列中的所有任务被处理掉。

案例1:创建队列,先进先出

importqueue

#先进先出队列

#put放数据,是否阻塞,阻塞时的超时时间

#get取数据

q=queue.Queue(2)#参数10代表队列最大长度为2个,如果满了就等待,或者报错

q.put(11)#放数据

q.put(22)

#如果放置的元素多于最大长度,则一直阻塞不出结果

#如果设置q.put(33,block=False)则超出元素直接报错

#如果设置timeout,则阻塞超时直接报错

# q.put(33,block=False,timeout=2)

print("队长度:",q.qsize())

print("取第一个数据",q.get())#取数据

print('队列最大元素数',q.maxsize)

效果:

案例2:创建队列,后进先出

importqueue

#后进先出

q=queue.LifoQueue()#继承queue类

q.put(11)

q.put(22)

q.put(33)

print("取第一个数据",q.get())#取数据

效果:

案例3:优先级队列

importqueue

#优先级队列

q=queue.PriorityQueue()

#需要元祖格式,第一个参数是优先级,数越低优先级越高

q.put((7,'11'))

q.put((5,'22'))

q.put((4,'33'))

print("取第一个数据",q.get())#取数据

效果:

案例4:双向队列

importqueue

#双向

q=queue.deque()

q.append(123)

q.append(456)

q.appendleft(789)

print(q.pop())

print(q.popleft())

效果:

2、生产者消费者模型:

生产者消费者也叫缓存绑定问题(bounded- buffer),是一个经典的、多进程同步问题,主要为了解决阻塞问题。生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据。在生产者和消费者之间产生一个队列/仓库(缓冲区),减少两者的耦合(依赖)作用。

有两个进程:一组生产者进程和一组消费者进程共享一个初始为空、固定大小为n的队列/缓存(缓冲区)。生产者的工作是制造一段数据,只有缓冲区没满时,生产者才能把消息放入到缓冲区,否则必须等待,如此反复; 同时,只有缓冲区不空时,消费者才能从中取出消息,一次消费一段数据(即将其从缓存中移出),否则必须等待。由于缓冲区是临界资源,它只允许一个生产者放入消息,或者一个消费者从中取出消息。

理论可参考:

http://www.2cto.com/kf/201510/446153.html

http://www.jb51.net/article/87385.htm

案例1:生产者消费者模型

importqueue

importthreading

importtime

q=queue.Queue(20)

defproductor(arg):#创建生产者

while True:

q.put("Pr"+str(arg)+'-东西')#生产者把生产的东西放进队列

foriinrange(300):

t=threading.Thread(target=productor,args=(i,))

t.start()

defconsumer(arg):#创建消费者

while True:

print('消费者',arg,'//',q.get())#消费者从队列中消费东西

time.sleep(2)#消费者的消费速度

forjinrange(3):

t=threading.Thread(target=consumer,args=(j,))

t.start()

执行结果:

链接:https://pan.baidu.com/s/1jKcQzgq 密码:2qf7

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180219G0P1SR00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券