Class CircularConcurrentLinkedDeque<E>

java.lang.Object
java.util.AbstractCollection<E>
java.util.concurrent.ConcurrentLinkedDeque<E>
org.mockserver.collections.CircularConcurrentLinkedDeque<E>
All Implemented Interfaces:
Serializable, Iterable<E>, Collection<E>, Deque<E>, Queue<E>

public class CircularConcurrentLinkedDeque<E> extends ConcurrentLinkedDeque<E>
A bounded ConcurrentLinkedDeque that evicts the oldest element(s) once it reaches maxSize, invoking an optional callback on each evicted element.

Why the explicit size counter: ConcurrentLinkedDeque.size() is documented as an O(n) operation (it walks the whole list). The eviction check runs on every add(E)/offer(E), so relying on super.size() made each insertion O(n) once the deque was full — the hot path for MockServer's request/event log. Under a sustained request load this manifested as CPU usage that climbed as the log filled and stayed high (GitHub issue #2329). An AtomicInteger maintained by every mutating method makes size() and the eviction check O(1).

The counter is kept consistent by every size-changing method on this class (add(E), offer(E), addAll(java.util.Collection<? extends E>) (via add), remove(java.lang.Object), removeItem(E), clear(), and the internal eviction). Callers must mutate the deque only through these methods (MockServer's MockServerEventLog does); direct use of other inherited bulk mutators is not supported by this subclass.

Author:
jamesdbloom
See Also: