У меня следующая ситуация:
- Структура данных, которую можно только продлить (я только когда-либо добавить вещи в хвост)
- Мне нужно уметь отслеживать, какие элементы у меня уже есть (у меня есть индекс, и в идеале я хочу начать перемещая список снова из этого конкретного элемента)
- Я бы хотел, чтобы чтения никогда не блокировались, и добавление новый элемент только блокирует хвост очереди, а не вся очередь
Это структура, которая сильно изменена несколькими потоками.
Какая была бы лучшая структура данных для этого?
ArrayList. Это было бы идеальным, чтобы иметь возможность прямого доступа к последнему элементу, видимому с использованием индекса, но это приводит к исключениям сопутствующих модификаций. я мог бы сделать его синхронизированным, но хотел бы избежать блокировки (или любой блокировки отдельно от самого последнего элемента, так как это единственный, где могут быть одновременные записи для добавления новых элементов)
ConcurrentLinkedQueue. Это решило бы мою проблему concurrency, но проблема в том, что мне нужно было бы сохранить текущую позицию итерации, а не целочисленный индекс. У этого есть проблема, что он возвращает слабо согласованный итератор, который не гарантирует возврат новых объектов, которые были добавлены в список с момента создания итератора (source: javadoc)
ConcurrentHashMap с индексом в виде ключей. Это имеет то преимущество, что я могу напрямую получить доступ к данным, соответствующим правильному индексу, но есть проблема, что нет оператора getNext, который позволит мне эффективно перемещать элементы из индекса, индексировать + 1 и т.д.
Векторы. Это позволило бы решить большинство моих проблем, разрешив что-то, что не будет бросать исключения одновременной модификации и допускать прямой доступ. Однако, учитывая, что все методы синхронизированы, производительность плоха по сравнению с аррайалистами. Учитывая, что я только хочу расширить структуру, а не вставлять записи посередине, я не желаю идти на это тяжелое весовое решение, где чтение также страдает от хита производительности (тогда как, учитывая мой usecase, индекс элемента никогда не меняется, поэтому нет необходимости синхронизировать чтения, которые не являются хвостом)
Пользовательская структура данных: сохраните массив объектов, которые я хочу сохранить, и указатель на хвост этого массива (последний набор элементов), при вставке нового объекта, заблокируйте хвост и объект, на который указывает хвост. Когда объект превышает свой текущий размер, операция блокировки изменяется.
Какая была бы лучшая стратегия/любая другая более эффективная реализация?