您的位置:首页 > 编程语言 > Python开发

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

2018-02-19 00:00 555 查看
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:创建队列,先进先出
import queue
#先进先出队列
#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:创建队列,后进先出import queue
#后进先出
q=queue.LifoQueue()#继承queue类
q.put(11)
q.put(22)
q.put(33)
print("取第一个数据",q.get())#取数据效果:

案例3:优先级队列
import queue
#优先级队列
q=queue.PriorityQueue()
#需要元祖格式,第一个参数是优先级,数越低优先级越高
q.put((7,'11'))
q.put((5,'22'))
q.put((4,'33'))
print("取第一个数据",q.get())#取数据效果:

案例4:双向队列import queue
#双向
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.htmlhttp://www.jb51.net/article/87385.htm
案例1:生产者消费者模型import queue
import threading
import time
q=queue.Queue(20)
def productor(arg):#创建生产者
   while True:
q.put("Pr"+str(arg)+'-东西')#生产者把生产的东西放进队列
for i in range(300):
t=threading.Thread(target=productor,args=(i,))
t.start()
def consumer(arg):#创建消费者
   while True:
print('消费者',arg,'//',q.get())#消费者从队列中消费东西
       time.sleep(2)#消费者的消费速度
for j in range(3):
t=threading.Thread(target=consumer,args=(j,))
t.start()执行结果:


链接:https://pan.baidu.com/s/1jKcQzgq 密码:2qf7
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: