2016-10-24 2 views
0

Могу ли я настроить Queue.Queue так, чтобы он всегда принимал новые элементы и просто удалял самый старый элемент, если очередь заполнена?Удалить самый старый элемент из очереди python.Queue (с синхронизацией)

Если нет, существует ли еще один класс очереди в стандартной библиотеке, который может это сделать?

(я не могу использовать Deque, потому что есть установка производитель/потребитель, где нужна синхронизация.)

+2

Вы можете использовать ['collections.deque'] (https://docs.python.org/2/library/collections.html#collections.deque), передавая параметр' maxlen' –

+0

А, но мне это нужно синхронизироваться. И похоже, что это будет не так просто, как просто защита с помощью мьютекса, так как я хочу блокировать потребительский поток до тех пор, пока не будет доступен элемент (а не опрос непрерывно). –

+0

Я тоже это понял. Я снова открыл –

ответ

1

Примера защиты доступа к ресурсам, используя условие, как я сказал в комментарии.

import collections 
import threading 
import time 

queue = collections.deque() 
condition = threading.Condition() 

def consumer(): 
    condition.acquire() 
    while True: 
     while queue: 
      item = queue.popleft() 
      condition.release() 
      # do something with item 
      print(item) 
      condition.acquire() 
     condition.wait() 

def push_item(item): 
    with condition: 
     queue.append(item) 
     condition.notify() 

# From that point forward, it is just demonstration code to show how to use 

def example_producer_thread(*args): 
    for arg in args: 
     push_item(arg) 

consumer_thread = threading.Thread(target=consumer, name='queue consumer') 
consumer_thread.daemon = True # so it does not prevent python from exiting 
consumer_thread.start() 

for example in [range(0, 10), range(10, 20), range(20, 30)]: 
    threading.Thread(target=example_producer_thread, args=example).start() 

time.sleep(1) # let the consumer thread some time before the script gets killed 

Ядро здесь:

  • consumer() является потребителем нить, он остается в режиме ожидания (без голосования), пока другой поток помещает элементы в очередь. При пробуждении он блокирует очередь, получает элемент, разблокирует очередь, обрабатывает элемент, пока в очереди не останется больше элементов. Затем он отпускает его и снова спит.
  • push_item() подталкивает один элемент в очередь и уведомляет потребительский поток, который он должен проснуться.

Остальное - это просто рабочий пример. example_producer_thread просто вставляет свои аргументы в очередь. И мы запускаем три из них, каждый из которых работает с диапазоном чисел, чтобы мы могли видеть результаты.

Просто добавьте maxlen в очередь, и вы хорошо пойдете. Возможно, инкапсулируйте функциональность в небольшом классе, пока вы на нем.