特点:
分类:
FIFO队列Queue(元素出入规则:先入先出)默认的
LIFO队列LifoQueue(元素出入规则:后入先出-类似栈(子弹弹夹模式))
优先级队列PriorityQueue
SimpleQueue 无界的 FIFO 队列构造函数。简单的队列,缺少任务跟踪等高级功能(3.7 新版功能.)
collections.deque 是无界队列的替代实现,具有快速原子的 append() 和 popleft() 操作,不需要锁定。(需要collections的包)
import time
import threading
class ThreadSafeQueue:
def __init__(self, max_size=0):
# 定义存储的元素列表
self.queue = []
# 最大的数据
self.max_size = max_size
# 线程互斥锁,保证多线程对列表操作的串行化
self.lock = threading.Lock()
# 定义的条件变量对象
self.condition = threading.Condition()
# 获取当前队列元素的数量--获取的过程也是进行互斥锁的
def size(self):
with self.lock:
size = len(self.queue)
return size
# 从队列里面获取元素
def get(self, index):
with self.lock:
item = self.queue[index]
return item
# 往队列里面放入元素
def put(self, item):
if self.max_size != 0 and self.size() > self.max_size:
return "队列已经满了!"
# 进行串行的添加对象
with self.lock:
print('写入元素: %s' % item)
self.queue.append(item)
print("当前队列的元素:", self.queue)
# 唤醒其他线程继续执行
with self.condition:
self.condition.notify()
# 批量插入元素
def batch_put(self, item_list):
for item in item_list:
self.put(item)
# 从队列取出元素block-是否需要阻塞的等待
def pop(self, block=True, timeout=None):
if self.size() == 0:
# 需要阻塞等待
if block:
with self.condition:
self.condition.wait(timeout=timeout)
else:
return None
# 进行安全的获取原始--加锁
with self.lock:
item = None
if len(self.queue) > 0:
item = self.queue.pop()
print("=====>" * 10)
print('从队列中获取元素: %s' % item)
print("=====>" * 10)
return item
class Producer(threading.Thread):
def run(self):
ssds = "你是一个大爷"
import random
while True:
item = random.choice(ssds)
queue.put(item)
time.sleep(1)
class Consumer(threading.Thread):
def run(self):
while True:
item = queue.pop(block=False, timeout=-1)
time.sleep(1)
if __name__ == '__main__':
queue = ThreadSafeQueue(max_size=100)
producer = Producer()
producer2 = Producer()
consumer = Consumer()
producer.start()
producer2.start()
consumer.start()
producer.join()
producer2.join()
consumer.join()
来自官方文档:
https://docs.python.org/zh-cn/3.7/library/queue.html
empty() 如果队列为空,返回True,反之False
qsize() 返回队列里元素数量,注意,qsize() > 0 不保证后续的 get() 不被阻塞,qsize() < maxsize 也不保证 put() 不被阻塞。
full() 判断对队列是否已满,返回True,反之False
get([block[, timeout]])获取队列,timeout等待时间
put(item, block=True, timeout=None)(放一个元素进队列) get(从队列中取出一个元素) 先进先出原则
PS:将 item 放入队列。如果可选参数 block 是 true 并且 timeout 是 None (默认),则在必要时阻塞至有空闲插槽可用。如果 timeout 是个正数,将最多阻塞 timeout 秒,如果在这段时间没有可用的空闲插槽,将引发 Full 异常。反之 (block 是 false),如果空闲插槽立即可用,则把 item 放入队列,否则引发 Full 异常 ( 在这种情况下,timeout 将被忽略)。
get_nowait(立即取出一个元素,不阻塞)
put_nowait(立即放入一个元素,不阻塞)
task_done(在完成一项任务之后,向任务已经完成的队列发送一个信号)
join(阻塞调用线程,直到队列中的所有任务被处理掉)
import queue
q = queue.Queue()
q.put('a')
print(q.get())
q.put('b')
print(q.get())
print(q.get())
上面:如果里面没有元素的时候,进行get()的获取的时候,会阻塞,它需要等待队列中存在数据了才会去获取。
import queue
q = queue.Queue()
q.put('a')
print(q.get())
# print(q.get())
print('队列是否为空:',q.empty())
print('队列元素数量',q.qsize())
q.put('b')
q.put('c')
q.put('d')
print('队列是否为空:',q.empty())
print('队列元素数量',q.qsize())
print(q.get())
print(q.get())
print(q.get())
输出
a
队列是否为空: True
队列元素数量 0
队列是否为空: False
队列元素数量 3
b
c
d
from queue import Queue
import time, threading
class Producer(threading.Thread):
def run(self):
ssds = "你是一个大爷"
import random
while True:
item = random.choice(ssds)
queue.put(item)
print('写入元素: %s' % item)
print('当前队列内容: %s' % queue.queue)
time.sleep(1)
class Consumer(threading.Thread):
def run(self):
while True:
try:
item = queue.get(block=False, timeout=1)
print("=====>" * 10)
print('从队列中获取元素: %s' % item)
print("=====>" * 10)
time.sleep(1)
queue.task_done()
except:
pass
if __name__ == '__main__':
# queue = ThreadSafeQueue(max_size=100)
queue = Queue(maxsize=100)
producer = Producer()
producer2 = Producer()
consumer = Consumer()
producer.start()
producer2.start()
consumer.start()
producer.join()
producer2.join()
consumer.join()
输出:
写入元素: 爷=====>=====>=====>=====>=====>=====>=====>=====>=====>=====>写入元素: 爷
当前队列内容: deque(['爷'])
当前队列内容: deque(['爷'])
从队列中获取元素: 爷
=====>=====>=====>=====>=====>=====>=====>=====>=====>=====>
写入元素: 大
当前队列内容: deque(['爷', '大'])写入元素: 一
=====>=====>=====>=====>=====>=====>=====>=====>=====>=====>
从队列中获取元素: 爷
=====>=====>=====>=====>=====>=====>=====>=====>=====>=====>当前队列内容: deque(['大', '一'])
写入元素: 你写入元素: 一=====>=====>=====>=====>=====>=====>=====>=====>=====>=====>
从队列中获取元素: 大
当前队列内容: deque(['一', '你', '一'])
当前队列内容: deque(['一', '你', '一'])
=====>=====>=====>=====>=====>=====>=====>=====>=====>=====>
写入元素: 爷写入元素: 爷
当前队列内容: deque(['一', '你', '一', '爷', '爷'])
当前队列内容: deque(['一', '你', '一', '爷', '爷'])
=====>=====>=====>=====>=====>=====>=====>=====>=====>=====>
从队列中获取元素: 一
from queue import LifoQueue
lifoQueue = LifoQueue()
lifoQueue.put("第1个进来")
lifoQueue.put("第2个进来")
lifoQueue.put("第3个进来")
print('当前队列内容:', lifoQueue.queue)
lifoQueue.get()
lifoQueue.get()
print('当前队列内容:', lifoQueue.queue)
输出:
当前队列内容: ['第1个进来', '第2个进来', '第3个进来']
当前队列内容: ['第1个进来']
优先队列让你能够以任意顺序添加对象,并随时(可能是在两次添加对象之间)找出(并删除)最小的元素。
可以使用对应的数据编号对应元素的排序权重
设置的值越小,优先级越高
可以用于快速访问容器中键值最小或最大的元素
PriorityQueue 线程安全的队列,提供锁语义来支持多个并发的生产者和消费者
有一定的开销,内部主要是基于heapq
示例1)排序后值小的,具有出栈的优先权
from queue import PriorityQueue # 优先队列
pq = PriorityQueue()
pq.put("第2-0个进来")
pq.put("第1-0个进来")
pq.put("第2-1个进来")
pq.put("第3个进来")
pq.put("第1-1个进来")
pq.put("第2-2个进来")
pq.put("第2-3个进来")
while not pq.empty():
print(pq.get())
输出:
第1-0个进来
第1-1个进来
第2-0个进来
第2-1个进来
第2-2个进来
第2-3个进来
第3个进来
示例2)使用元祖的形式传入,并编号
from queue import PriorityQueue # 优先队列
pq = PriorityQueue()
pq.put((2,"第2个进来"))
pq.put((0,"第0个进来"))
pq.put((0,"第0-0个进来"))
pq.put((1,"第1个进来"))
pq.put((2,"第2.2个进来"))
while not pq.empty():
print(pq.get())
输出:
(0, '第0-0个进来')
(0, '第0个进来')
(1, '第1个进来')
(2, '第2.2个进来')
(2, '第2个进来')
异常的情况:
from queue import PriorityQueue # 优先队列
pq = PriorityQueue()
pq.put((0,3))
pq.put((0,"第0-0个进来"))
while not pq.empty():
print(pq.get())
输出错误:
heappush(self.queue, item)
TypeError: '<' not supported between instances of 'str' and 'int'
因为优先队列内部内部使用的是堆排序。所以必须保证入栈的元素能够进行大小的比较(同类型)。
关于python中的heapq:
关于堆的了解: https://blog.csdn.net/weixin_45459565/article/details/103911510
from collections import deque
q = deque()
print('右侧添加一个元素:',q.append('你好'),'元素列表内容:',q)
print('右侧添加一个元素:',q.append('我是你大爷'),'元素列表内容:',q)
print('右侧添加一个元素:',q.append('你妹'),'元素列表内容:',q)
print('右侧添加一组元素:',q.extend(['吃饭','睡觉','打豆豆']),'元素列表内容:',q)
print("队列内容",q)
print('左弹出元素:',q.popleft(),'元素列表内容:',q)
print('右弹出元素:',q.pop(),'元素列表内容:',q)
print('左边添加一个元素:',q.appendleft("我是谁"),'元素列表内容:',q)
print('左边添加一组元素:',q.extendleft(["大爷","小爷",'大少爷']),'元素列表内容:',q)
print('顺时针-翻转队列:',q.rotate(1),'元素列表内容:',q)
print('逆时针-翻转队列:',q.rotate(-1),'元素列表内容:',q)
print('队列翻转1:',q.reverse(),'元素列表内容:',q)
print('队列翻转2:',q.reverse(),'元素列表内容:',q)
print('判断元素是否在队列中:',('大少爷' in q))
print('判断元素是否在队列中:',('我是你大爷' in q))
print('判断元素是否在队列中:',('我是你大爷-哈哈' in q))
print("当前区间列表:","['大少爷', '小爷', '大爷', '我是谁', '我是你大爷', '你妹', '吃饭', '睡觉']")
print('判断元素索引的索引-指定查找的区间(注意这个区间范围[0,5]如果再这个索引区间内找不到会找不到这个值的错误,索引是4)',(q.index("我是你大爷",0,5) ))
输出:
右侧添加一个元素: None 元素列表内容: deque(['你好'])
右侧添加一个元素: None 元素列表内容: deque(['你好', '我是你大爷'])
右侧添加一个元素: None 元素列表内容: deque(['你好', '我是你大爷', '你妹'])
右侧添加一组元素: None 元素列表内容: deque(['你好', '我是你大爷', '你妹', '吃饭', '睡觉', '打豆豆'])
队列内容 deque(['你好', '我是你大爷', '你妹', '吃饭', '睡觉', '打豆豆'])
左弹出元素: 你好 元素列表内容: deque(['我是你大爷', '你妹', '吃饭', '睡觉', '打豆豆'])
右弹出元素: 打豆豆 元素列表内容: deque(['我是你大爷', '你妹', '吃饭', '睡觉'])
左边添加一个元素: None 元素列表内容: deque(['我是谁', '我是你大爷', '你妹', '吃饭', '睡觉'])
左边添加一组元素: None 元素列表内容: deque(['大少爷', '小爷', '大爷', '我是谁', '我是你大爷', '你妹', '吃饭', '睡觉'])
顺时针-翻转队列: None 元素列表内容: deque(['睡觉', '大少爷', '小爷', '大爷', '我是谁', '我是你大爷', '你妹', '吃饭'])
逆时针-翻转队列: None 元素列表内容: deque(['大少爷', '小爷', '大爷', '我是谁', '我是你大爷', '你妹', '吃饭', '睡觉'])
队列翻转1: None 元素列表内容: deque(['睡觉', '吃饭', '你妹', '我是你大爷', '我是谁', '大爷', '小爷', '大少爷'])
队列翻转2: None 元素列表内容: deque(['大少爷', '小爷', '大爷', '我是谁', '我是你大爷', '你妹', '吃饭', '睡觉'])
判断元素是否在队列中: True
判断元素是否在队列中: True
判断元素是否在队列中: False
当前区间列表: ['大少爷', '小爷', '大爷', '我是谁', '我是你大爷', '你妹', '吃饭', '睡觉']
判断元素索引的索引-指定查找的区间(注意这个区间范围0,5,-我是你大爷索引是4,如果再这个索引区间内找不到会找不到这个值的错误): 4
个人其他博客地址
简书:https://www.jianshu.com/u/d6960089b087
掘金:https://juejin.cn/user/2963939079225608
小钟同学 | 文 【原创】| QQ:308711822
1:本文相关描述主要是个人的认知和见解,如有不当之处,还望各位大佬指正。 2:关于文章内容,有部分内容参考自互联网整理,如有链接会声明标注;如没有及时标注备注的链接的,如有侵权请联系,我会立即删除处理哟。
原文作者:程序员小钟同学;如有侵权,请联系管理员删除。