Очередь фиксированного размера, которая автоматически удаляет старые значения при новых запросах - PullRequest
108 голосов
/ 02 мая 2011

Я использую ConcurrentQueue для общей структуры данных, целью которой является сохранение последних N объектов, переданных ей (вид истории).

Предположим, у нас есть браузер, и мы хотим, чтобы последний100 просмотренных URL.Мне нужна очередь, которая автоматически удаляет (удаляет из очереди) самую старую (первую) запись при вставке новой записи (ставит в очередь), когда емкость заполняется (100 адресов в истории).

Как мне это сделать, используя System.Collections

Ответы [ 11 ]

0 голосов
/ 03 декабря 2015

Это моя версия очереди:

public class FixedSizedQueue<T> {
  private object LOCK = new object();
  ConcurrentQueue<T> queue;

  public int MaxSize { get; set; }

  public FixedSizedQueue(int maxSize, IEnumerable<T> items = null) {
     this.MaxSize = maxSize;
     if (items == null) {
        queue = new ConcurrentQueue<T>();
     }
     else {
        queue = new ConcurrentQueue<T>(items);
        EnsureLimitConstraint();
     }
  }

  public void Enqueue(T obj) {
     queue.Enqueue(obj);
     EnsureLimitConstraint();
  }

  private void EnsureLimitConstraint() {
     if (queue.Count > MaxSize) {
        lock (LOCK) {
           T overflow;
           while (queue.Count > MaxSize) {
              queue.TryDequeue(out overflow);
           }
        }
     }
  }


  /// <summary>
  /// returns the current snapshot of the queue
  /// </summary>
  /// <returns></returns>
  public T[] GetSnapshot() {
     return queue.ToArray();
  }
}

Я считаю полезным иметь конструктор, построенный на IEnumerable, и считаю полезным иметь GetSnapshot, чтобы иметь многопоточный безопасный список (в данном случае это массив) элементов на момент вызова, которые не вызывают ошибок, если изменяется базовая коллекция.

Двойная проверка счетчика предназначена для предотвращения блокировки при некоторых обстоятельствах.

...