В своем приложении я уже некоторое время использую ArrayList, и теперь мне нужно иметь доступ к нему из разных потоков. Я много читаю и много пишу. Этот список является частным членом класса, и у меня есть геттер для доступа к нему из других классов.
Простая замена моего ArrayList
на CopyOnWriteArrayList
работает, но я боюсь потери производительности (мой список содержит координаты GPS, обновляемые каждые 2 секунды, и я бы хотел, чтобы он работал как можно дольше).
Использование Collections.synchronizedList
также работает, если я оборачиваю каждый доступ к получателю списка в synchronized() {}
block, что означает, что мне нужно go через весь код приложения для проверки.
Я пытался:
- объявить мой получатель как
synchronized
- обернуть
return myList;
моего геттера в синхронизированный блок
Но оба приводят к ConcurrentModificationException
при чтении списка во время его записи.
Есть ли лучший вариант, чем CopyOnWriteArrayList
или добавление блоков synchronized() {}
повсюду?
Если это важно, это приложение Android.
РЕДАКТИРОВАТЬ: вот некоторый код, иллюстрирующий мои две попытки с использованием геттера:
ArrayList<MyObject> mList = Collections.synchronizedList(new ArrayList<>());
public ArrayList<MyObject> getList() {
synchronized(this) {
return mList;
}
}
public synchronized ArrayList<MyObject> getList() {
return mList;
}
РЕДАКТИРОВАТЬ 2: вот дополнительная информация о варианте использования, следуя @Martin Marconci ni комментарии:
- приложение может загружать файлы KML (файлы, содержащие такие функции, как маркеры, линии и многоугольники) на карту Google
- У меня есть класс Map, в котором ArrayLists содержит ссылки на каждый загруженная функция. У этого класса есть метод load (Feature f), который загружает данную функцию на карту Google и сохраняет ее в подходящий список ArrayList (либо маркеры, либо список линий, либо список многоугольников).
- У меня есть класс KmlFileLoader, анализирующий KML files
- У меня есть класс KmlFile, в котором ArrayLists содержат ссылки на все функции файла (которые могут быть загружены на карту или нет). У этого класса есть loadOnMap (карта карты), который будет вызывать map.load (Feature f) для каждой функции. Здесь происходит ConcurrentModification: если я обращаюсь к функциям карты во время загрузки в нее файла.
На самом деле, в моем коде не так много мест, где я повторяю списки за пределами Класс карты, поэтому решить проблему для этого проекта с помощью синхронизированных блоков намного проще, чем я думал изначально. Внутри класса карты я уже синхронизировал все методы доступа к спискам, поэтому здесь нет никаких проблем (мне даже не нужно использовать Collections.synchronizedList, так как я синхронизируюсь с объектом Map).
Но мне все еще интересно знать, есть ли лучший вариант, чем использование CopyOnWriteArrayList и перенос моих геттеров в синхронизированные блоки. Думаю, нет.