[英]Python PriorityQueue items of same priority got in random order
我使用queue.Queue
class 將任務從一個線程傳遞到另一個線程。 后來我需要添加優先級,所以我將其更改為PriorityQueue
,使用建議的PrioritizedItem
(因為任務是 dict 並且無法比較)。 然后,在極少數情況下,它開始導致任務混淆。 我花了一段時間才意識到/調試PriorityQueue
中的相同優先級項目不會保持插入順序,或者從調試的角度來看更糟糕的是,通常它們會保持插入順序。
我想,在談論任務隊列時,FIFO 是一種默認值。 這就是為什么Queue
不像FifoQueue那樣被調用的原因,不是嗎? 因此, PriorityQueue
應該明確 state 不是等優先級項目的 FIFO。 不幸的是,Python 文檔沒有警告我們這一點,缺乏警告讓我很頭疼,可能其他人也很頭疼。
我還沒有找到任何現成的解決方案,但我很確定其他人可能需要一個PriorityQueue
來保持同等優先級項目的插入順序。 所以這張票...
此外,我希望 Python 文檔將 state 在下一個版本中發出警告,讓我分享一下我是如何解決這個問題的。
heapq
(由PriorityQueue
使用)建議我們需要在 item 的 compare 部分插入一個序列號,以便計算出的優先級顯而易見,避免有 2 個 item 具有相同的優先級。
我還添加了threading.Lock
,這樣我們就可以避免因為發生了一些線程競爭情況而使 2 個項目具有相同的序列號。
class _ThreadSafeCounter(object):
def __init__(self, start=0):
self.countergen = itertools.count(start)
self.lock = threading.Lock()
def __call__(self):
with self.lock:
return self.countergen.__next__()
#create a function that provides incremental sequence numbers
_getnextseqnum = _ThreadSafeCounter()
@dataclasses.dataclass(order=True)
class PriorityQueueItem:
"""Container for priority queue items
The payload of the item is stored in the optional "data" (None by default), and
can be of any type, even such that cannot be compared, e.g. dict.
The queue priority is defined mainly by the optional "priority" argument (10 by
default).
If there are more items with the same "priority", their put-order is preserved,
because of the automatically increasing sequence number, "_seqnum".
Usage in the producer:
pq.put(PriorityQueueItem("Best-effort-task",100))
pq.put(PriorityQueueItem(dict(b=2))
pq.put(PriorityQueueItem(priority=0))
pq.put(PriorityQueueItem(dict(a=1))
Consumer is to get the tasks with pq.get().getdata(), and will actually receive
None
{'b':2}
{'a':1}
"Best-effort-task"
"""
data: typing.Any=dataclasses.field(default=None, compare=False)
priority: int=10
_seqnum: int=dataclasses.field(default_factory=_getnextseqnum, init=False)
def getdata(self):
"""Get the payload of the item in the consumer thread"""
return self.data
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.