Python中的queue.queue和collections.deque都提供了队列数据结构的实现,但它们之间有些许的不同。
queue.queue和collections.deque的主要区别
queue.queue和collections.deque的主要区别包括以下几点:
实现机制
queue.queue是Python标准库提供的声明式队列(FIFO)结构,它是线程安全的。queue.Queue底层使用线程锁来保证安全访问。它里面含有的成员函数,如put, get,task_done, join都是线程安全的。
collections.deque也是Python标准库中的一个数据结构,它是非线程安全的,不提供线程安全的保障,但提供了既可以在队列头部和队列尾部插入与删除的双端队列。deque底层使用的是双向链表,插入、删除的时间复杂度为O(1),相对于queue.Queue速度更快。
应用场景
queue.Queue一般用于多线程的场景,如果只是单线程的场景,建议使用deque,前者在多线程环境下使用相对安全些,能够保证“线出、线进”;后者在性能上相对高效一些,但不适用于多线程环境,尤其不适用于多个线程同时put和get一个队列,可能会出现混乱。
使用方式
queue.Queue使用常见如下:
import queue
q = queue.Queue()
q.put("value")
q.get()
q.task_done()
q.join()
collections.deque使用常见如下:
import collections
dq = collections.deque()
dq.append("value")
dq.popleft()
示例说明
示例1
以下示例说明queue.Queue实现线程安全的过程
import threading
import queue
def consumer(q):
while True:
if not q.empty():
print("consume value:{}".format(q.get()))
q.task_done()
else:
break
q = queue.Queue()
for i in range(10):
q.put(i)
threads = []
for i in range(5):
t = threading.Thread(target=consumer, args=(q,))
threads.append(t)
t.start()
q.join()
for t in threads:
t.join()
在上述示例中,创建了一个queue.Queue实例,将10个数字放入队列中,创建5个消费者线程,从队列中依次取出数字进行消费,直到队列为空。queue.Queue实现线程安全的方式是采用线程锁,使用get(), put(), task_done(), join()等成员函数时都是线程安全的。
示例2
以下示例说明collections.deque实现双向队列的过程:
import collections
dq = collections.deque()
dq.append(1)
dq.appendleft(2)
dq.append("end")
print(dq)
print(dq.pop())
print(dq.popleft())
print(dq)
在上述示例中,创建了一个collections.deque实例,使用append()和appendleft()函数在队列尾部和队列头部插入元素,使用pop()和popleft()函数在队列尾部和队列头部删除元素。deque在使用上更灵活,可以在队列尾部和队列头部插入与删除数据。