您的位置:

优化并发性能,Python中的deque和queue可助力

一、deque和Queue简介

Python中的deque和queue模块可以用来优化并发性能。deque(双端队列)是一个线程安全的可变序列,支持线程安全的对头和尾添加、删除元素。queue(队列)是在多线程编程中非常有用的一种数据结构,它可以帮助我们在多个线程之间安全、可靠地共享信息,在一些需要异步处理的任务处理中尤为重要。

在Python的标准库中,有三个步骤来实现队列。第一步是创建一个队列;第二步是向队列中添加元素;第三步是从队列中获取元素。对于Python的deque和queue模块,我们可以使用以下方法来创建队列:


from collections import deque
queue = deque(maxlen=10)
queue.append(1)
print(queue)  # deque([1], maxlen=10)

import queue
q = queue.Queue()
q.put(1)
print(q.get())  # 1

二、deque的使用方法

deque比列表更高效,因为它支持O(1)时间复杂度的添加和删除,而列表的时间复杂度则为O(n)。deque可以在两端添加和删除元素,具有高效的内存使用,可用于处理大量数据,尤其是需要进行append和popleft运算的情况。

以双端队列的基本操作为例,以下是一些常用的deque方法:


from collections import deque
queue = deque(maxlen=10)
queue.append(1) # 右端加入元素
queue.appendleft(2) # 左端加入元素
queue.pop() # 右端删除一个元素,并返回该元素的值
queue.popleft() # 左端删除一个元素,并返回该元素的值
queue.clear() # 清空队列
print(queue)

deque还可以用于在线程安全中,例如多个Python线程可以安全地从队列的左端添加或删除元素。这使得deque非常适合于异步处理任务。


import threading
import time
from collections import deque

queue = deque(maxlen=10)

def consume():
    while True:
        if len(queue) > 0:
            print(queue.popleft())
        time.sleep(1)

def produce():
    counter = 0
    while True:
        if len(queue) < queue.maxlen:
            queue.append(counter)
            counter +=1
        time.sleep(1)

threading.Thread(target=consume).start()
threading.Thread(target=produce).start()
在上面的代码中,我们使用deque实现了一个简单的“生产者-消费者”模式程序。通过两个Python线程,producer和consumer共享同一个queue对象,生产者在队列中添加元素,消费者从队列中删除元素。当生产者生产数量大于设定的队列最大长度时,它暂停生产并等待消费者继续消费。

三、queue的使用方法

如果您需要在Python中实现队列,基于deque的队列是一种很好的选择。但是,Python标准库中已经提供了一个内置的queue模块,其实现了一个多线程安全的FIFO队列。在Python多线程应用程序中,queue非常适合用于协调线程和处理任务。多个线程可以同时添加或获取元素,而不会破坏队列的结构。

以下是queue模块的一些示例:


import queue
q = queue.Queue()
q.put(1) # 添加元素到队列中
q.get() # 从队列中获取元素

Queue类还有许多有用的方法,以下是一些常见的方法:

1. 队列大小: Queue.qsize()

2. 检查队列是否为空: queue.empty()

3. 检查队列是否已满: queue.full()

4. 阻塞获取元素: queue.get()

5. 阻塞添加元素: queue.put()


import threading
import time
import queue

def consume(q):
    while True:
        item = q.get()
        print(item)
        q.task_done()

def produce(q):
    for item in range(100):
        q.put(item)
    q.join()

q = queue.Queue(10)
threads = [threading.Thread(target=consume, args=(q,)) for i in range(3)]
[q.start() for thread in threads]
q.join()
在上面的代码中,我们使用queue实现了一个简单的生产者消费者模型。queue提供了一个线程安全的队列,线程可以在队列尾部添加项目,或者从队列头部获取项目。可以看到,queue模块的实现非常简单,它为我们提供了一个非常方便的进行异步、线程安全的任务处理。