java - Android Set 上的 ConcurrentModificationException

标签 java android concurrency

我已经阅读了许多有关此问题的SO问题,但我无法理解为什么我会遇到java.util.ConcurrentModificationException

在类里面我有这个:

private Set<RequestOrders> mRequests = new HashSet<>();
private final Object lock = new Object();

mRequest 对象上的所有操作都被这样的同步语句包围:

public void handleOrder(RequestOrders order) {
    synchronized (lock) {
        if (!mRequests.contains(order)) {
            final sOrder = saveOrderOnDB(order);
            mRequests.add(sOrder);

            handleOrder(sOrder;
        }
    }
}

我收到以下错误:

void notifyOrder(int type) {
    if (!mPause) {
        synchronized (lock) {
            for (RequestOrders request : mRequests) { // Error here while iterating
                if (.....) {
                    redirectOrders(request);
                } else if (....) {
                    ......
                    startService(.....);
                }
            }
        }
    } else {
        .....
    }
}

知道为什么吗?同步语句不应该防止并发问题吗?

最佳答案

看起来,当您仍在迭代 mRequest 集时,可能会发生从集合中添加/删除 RequestOrders 的方法调用。因此,当您仍在迭代时,mRequest 集的大小正在发生变化,这会导致错误。要克服这个问题,您可以:

1 - 创建一个临时集,其中包含要添加到 mRequest 的所有对象。循环完 mRequest 集中的所有对象后,将临时集中的所有对象添加到 mRequest 集中。

2- 使用并发 HashMap。

以下是如何使用第一种方法的示例:

private Set<RequestOrders> mRequests = new HashSet<>();
private Set<RequestOrders> backlog = new HashSet<>();

public void handleOrder(RequestOrders order) {
    synchronized (lock) {
        if (!mRequests.contains(order)) {
            final sOrder = saveOrderOnDB(order);
            backlog.add(sOrder);
            handleOrder(sOrder);
        }
    }
}

void notifyOrder(int type) {
    if (!mPause) {
        for (RequestOrders request : mRequests) { // Error here while iterating
            if (.....) {
                redirectOrders(request);
            } else if (....) {
                ......
                startService(.....);
            }
        }
        mRequests.addAll(backlog);
        backlog.clear();
    } else {
        .....
    }
}

关于java - Android Set 上的 ConcurrentModificationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40676739/

相关文章:

Java - 解释这个正则表达式 (",(?=([^\"]*\"[^\"]*\")*[^\"]*$)", -1)

java - 在 Jboss 7.1 上部署 datasource.xml

java - Eclipse:无法执行dex:多个dex文件定义Landroid/support/v4/

javascript - phonegap/cordova onDeviceReady() 不触发 android 4.1.2

java - 当两个并发线程尝试从 CopyOnWriteArrayList 中删除元素时会发生什么? java

java - JTable 中更快的搜索算法

android - 使用opengles,android播放视频

django - 如何修复 Django 的 get_or_create() 并发导致数据重复

Java并发主题: publication of objects or its internal state

java - 我可以在 wicket 生成的 html 页面上使用 Selenium 访问属性键吗?