I am trying to implement an insertion-performance-focused, queue-like data structure that must meet the following requirements:
- Must be thread-safe
- Must be able to add to queue without synchronizing
- Must be able to get a "snapshot" view of the queue
My issue is getting the 'snapshot' view in a way that doesn't require synchronization of the insert. Since I can block the removal and elements can only be added to the end, getting the elements shouldn't be an issue. The problem I keep running into is that the LinkedList's iterator has an unsupressable concurrent modification fast-fail baked in and 'LinkedList.get(int)' is O(n).
Below is a pared-down example of where I am with what should be a fairly simple task.
public class SnapshotableQueue<T> {
private final LinkedList<T> queue = new LinkedList<>();
private final Object removeLock = new Object();
public void add(T element) {
queue.add(element);
}
public T remove() {
synchronized(removeLock) {
return queue.remove();
}
}
public List<T> getSnapshot() {
synchronized(removeLock) {
int length = queue.size();
List<T> snapshot = new ArrayList<>(length);
???
return snapshot;
}
}
}
Unacceptable Solution #1
for(int i = 0; i < length; i++)
snapshot.add(snapshot.get(i));
'LinkedList.get(int)' is O(n)
Unacceptable Solution #2
Iterator<T> iterator = queue.iterator();
for(int i = 0; i < length; i++)
snapshot.add(iterator.next());
Isn't thread-safe (throws ConcurrentModificationException)
Unacceptable Solution #3
Change queue to ArrayList
'ArrayList.remove(0)' is O(n)