在线程中拥有具有Queue优点的双端队列

问题描述 投票:0回答:3

我需要一个结构,我可以在右侧弹出()和追加()(就像双端队列一样),同时让结构在为空时阻塞并等待(就像队列一样)。我可以直接使用队列,但我还需要双端队列的良好功能,如果结构已满,则可以在不阻塞的情况下删除项目。

from collections import deque
d = deque(maxlen=2)
d.append(1)
d.append(2)
d.append(3) # d should be [2,3] (it is the case)
d.pop()
d.pop()
d.pop() # should wait (not the case)

子类化 deque(使其等待)或 Queue(添加 popLeft 函数)更好吗?

python python-3.x multithreading queue deque
3个回答
5
投票

不确定哪个更好,但这里有一个用 threading.Event

 添加 
wait on pop

的想法
from collections import deque
from threading import Event

class MyDeque(deque):
    def __init__(self, max_length):
        super().__init__(maxlen=max_length)
        self.not_empty = Event()
        self.not_empty.set()

    def append(self, elem):
        super().append(elem)
        self.not_empty.set()

    def pop(self):
        self.not_empty.wait()  # Wait until not empty, or next append call
        if not (len(q) - 1):
            self.not_empty.clear()
        return super().pop()

q = MyDeque(2)
q.append(1)
q.append(2)
q.append(3)
q.pop()
q.pop()
q.pop()  # Waits 

2
投票

创建自己的队列,混合两者的优点怎么样?

import queue as Queue
from collections import deque

class QueuePro:
  def __init__(self, maxlenDeque): 
    self.deque = deque(maxlen=maxlenDeque)
    self.queue = Queue.Queue()

  def append(self, elem):
    self.deque.append(elem)
    self.queue.put(elem)

  def pop(self):
    if(not self.deque):
      self.queue.get()
    else:
      self.deque.pop()
      self.queue.get()


q2 = QueuePro(2)
q2.append(1)
q2.append(2)

q2.pop()
q2.pop()
q2.pop()
#waiting

0
投票

基于Cisco提供的解决方案,我提供此解决方案是为了解决两个问题:1)删除构造函数中的set()操作,该操作在创建队列后执行弹出操作会导致错误。 2) 在多线程从队列读取的情况下确保队列安全。

from collections import deque
from threading import Event
from threading import Lock

class BlockingDeque(deque):
    def __init__(self, max_length):
        super().__init__(maxlen=max_length)
        self.not_empty = Event()
        self.lock = Lock()

    def append(self, elem):
        super().append(elem)
        self.not_empty.set()

    def popleft(self):
        self.lock.acquire()
        self.not_empty.wait()
        if not (len(self) - 1):
            self.not_empty.clear()
        toReturn = super().popleft()
        self.lock.release()    
        return toReturn
© www.soinside.com 2019 - 2024. All rights reserved.