queue队列
queue is especially useful in threaded programming when information must be exchanged safely between multiple threads
- queue在使用多进程之间交换安全信息的时候特别有用
- class
queue.
Queue
(maxsize=0) #先进先出
- class
queue.
LifoQueue
(maxsize=0) #后进先出 - class
queue.
PriorityQueue
(maxsize=0) #存储数据时可设置优先级的队列 优先级最小最先取出 - exception
queue.
Empty 正常情况下当队列为空则阻塞,如果设置了get_nowaait则会报该异常
- Exception raised when non-blocking
get()
(orget_nowait()
) is called on aQueue
object which is empty. - exception
queue.
Full 当设置了put_nowait,队列满时报异常
Exception raised when non-blocking put()
(or put_nowait()
) is called on a Queue
object which is full.
Queue.
qsize
() 查看队列大小
Queue.
empty
() #return True if empty 队列为空返回True
Queue.
full
() # return True if full
Queue.
put
(item, block=True, timeout=None) 上传到队列 正常当Q满了 在put就阻塞 如果timeout为True 则等待多少秒后直接抛异常
Queue.
put_nowait
(item)# 队列满直接抛异常Queue.
get
(block=True, timeout=None) #上传到队列,队列空了阻塞(block为阻塞,如果取不到数据就卡主,timeout设置的是卡主的时间)Queue.
get_nowait
() 队列没数据直接抛异常Queue.
task_done
() # q.task_done() 在完成一项工作之后,q.task_done() 函数向任务已经完成的队列发送一个信号.Queue.
join
() 实际上意味着等到队列为空,再执行别的操作
import queue#在python2是Queue,python3是queue q = queue.Queue() q.put('d1') q.put('d2') q.put('d3') print(q.qsize()) print(q.get()) print(q.get()) print(q.get()) print(q.qsize()) # print(q.get())#取完之后,再取会卡主,为防止卡主,可以使用Queue.get_nowait(),队列没数据直接抛异常:q.get_nowait() # q.get(block=False)#block默认我True,取不到数据就卡主,可以设置为False,取不到数据直接说明出错,空队列。 q = queue.Queue(maxsize=3)#maxsize设置的是队列的大小 q.put(1) q.put(2) q.put(3) # q.put(4)#超过队列大小,存不下了,卡主 q.put(timeout=1)#超时设置,卡出超过设置的时间,就退出
结果:
Traceback (most recent call last): File "C:/Users/Administrator/Desktop/py_work/drawData.py", line 19, in <module> q.put(timeout=1)#超时设置,卡出超过设置的时间,就退出 TypeError: put() missing 1 required positional argument: 'item' 3 d1 d2 d3 0
import queue q = queue.LifoQueue()#后进后出 q.put('d1') q.put('d2') q.put('d3') print(q.qsize()) print(q.get()) print(q.get()) print(q.get())
结果:
3
d3
d2
d1
import queue q = queue.PriorityQueue()#有VIP数据的队列 q.put((10,'qiqi'))#优先级和数据要放在元组中,优先级最小最先取出 q.put((-1,'shishi')) q.put((3,'mengmeng')) q.put((6,'tianqi')) print(q.get()) print(q.get()) print(q.get()) print(q.get())
结果:
(-1, 'shishi') (3, 'mengmeng') (6, 'tianqi') (10, 'qiqi')
生产者消费者模型
在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。
为什么要使用生产者和消费者模式
在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。
什么是生产者消费者模式
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
下面来学习一个最基本的生产者消费者模型的例子
import threading,queue,time def producer(name): count = 1 while True: q.put("骨头 %s" % count) print('生产了骨头',count) count += 1 time.sleep(2)#每2s生产一个骨头 def consumer(name): while True: print("%s 取到 %s,并且吃了它" %(name, q.get())) time.sleep(1)#每1s吃一个骨头,如果生产过快会供大于求,可以改了看看结果 q = queue.Queue(maxsize=10)#实例化一个队列,最多放10个骨头 p = threading.Thread(target=producer,args=('qiqi',) ) c1 = threading.Thread(target=consumer,args=('女生',) ) c2 = threading.Thread(target=consumer,args=('少妇',) ) p.start() c1.start() c2.start()
结果:
生产了骨头 1 女生 取到 骨头 1,并且吃了它 生产了骨头 2 少妇 取到 骨头 2,并且吃了它 生产了骨头 3 女生 取到 骨头 3,并且吃了它 生产了骨头 4 少妇 取到 骨头 4,并且吃了它 女生 取到 骨头 5,并且吃了它 生产了骨头 5 生产了骨头 6 少妇 取到 骨头 6,并且吃了它 生产了骨头 7 女生 取到 骨头 7,并且吃了它 生产了骨头 8 少妇 取到 骨头 8,并且吃了它 生产了骨头 9 女生 取到 骨头 9,并且吃了它 生产了骨头 10 少妇 取到 骨头 10,并且吃了它 生产了骨头 11 女生 取到 骨头 11,并且吃了它 生产了骨头 12 少妇 取到 骨头 12,并且吃了它 生产了骨头 13 女生 取到 骨头 13,并且吃了它 生产了骨头 14 少妇 取到 骨头 14,并且吃了它 生产了骨头 15 女生 取到 骨头 15,并且吃了它 生产了骨头 16 少妇 取到 骨头 16,并且吃了它 生产了骨头 17 女生 取到 骨头 17,并且吃了它 生产了骨头 18 少妇 取到 骨头 18,并且吃了它 生产了骨头 19 女生 取到 骨头 19,并且吃了它 ......
面试最有可能会问:
队列的主要作用:
- 解耦---使程序直接实现松耦合(一个模块修改,不会影响其他的)
- 提高处理效率。
队列的几种模式:
- FIFO=FIRST IN FIRST OUT 先进先出
- LIFO=LAST IN FIRST OUT 后进先出
队列和列表的区别:队列是先进先出(FIFO),就是先写进去的数据就先被读出来,取完就没了。列表取数据,相当于复制了份数据,列表中原有的数据还存在。