Добавление или удаление в SynchronizedMap и синхронизированных блоков - PullRequest
0 голосов
/ 17 сентября 2018

Я использую AWS Android SDK для загрузки файлов изображений в корзину S3. Я делаю операцию обрезки в потоке, который начинает передачу файла изображения после обрезки. Я сохраняю все экземпляры TransferObserver на карте, как указано и инициализировано ниже:

private Map<String, TransferObserver> transferObservers;

A() {
    transferObservers = Collections.synchronizedMap(new LinkedHashMap<String, TransferObserver>());
}

public void add(Image image) {
    handler.post(new Runnable() {
        @Override
        public void run() {
            // Cropping
            ...
            TransferObserver uploadObserver = transferUtility.upload(key, new File(localFilePath));
            uploadObserver.setTransferListener(new TransferListener() {
            photoTransferObservers.put(image.getPath(), uploadObserver);
        }
    }
}

Изображение может быть удалено, поэтому его запись на карте:

public void deleteTransferRecord(String key) {
    transferObservers.remove(key);
}

Существует также другая функция, которая возвращает общий процесс загрузки:

private void notifyListeners() {
    int completedUploadCount = 0;
    for (TransferObserver transferObserver : transferObservers.values()) {
        if (transferObserver.getState() == TransferState.COMPLETED) {
            completedUploadCount++;
        }
    }
    ...
}

Я получил исключение - которое я не учел - о попытке удаления во время итерации на transferObservers. Как мне обновить мой код, чтобы избежать проблем с параллелизмом?

1 Ответ

0 голосов
/ 17 сентября 2018

Вы можете синхронизировать через transferObservers везде, где у вас есть доступ (будь то добавление, удаление или чтение).В этот момент вам не нужно Collections.synchronizedMap.

. Или более простое решение - просто скопировать значения перед итерацией в notifyListeners.Таким образом, удаление или добавление в наблюдатели переноса не вызовет ConcurrentModificationException во время итерации.

private void notifyListeners() {
    int completedUploadCount = 0;
    List<TransferObserver> observers = new ArrayList<>(transferObservers.values());
    for (TransferObserver transferObserver : observers) {
        if (transferObserver.getState() == TransferState.COMPLETED) {
            completedUploadCount++;
        }
    }
    ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...