向SynchronizedMap和同步块添加或删除

时间:2018-09-16 23:29:55

标签: java android collections aws-sdk

我正在使用AWS Android SDK将图像文件上传到S3存储桶。我在线程中进行裁剪操作,该操作在裁剪完成后开始传输图像文件。我将所有TransferObserver实例保存在下面定义和初始化的Map中:

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 :(得分:0)

您可以在任何访问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++;
        }
    }
    ...
}