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
领取专属 10元无门槛券
私享最新 技术干货