尝试更新全局变量时出现 java.util.ConcurrentModificationException

标签 java android multithreading

我在方法中有以下代码( Utils.currentPrinters 是静态 JsonObject ):

    JsonObject printers = Utils.currentPrinters;

    for (Map.Entry<String, ?> entry : Utils.currentPrinters.entrySet()) {

        String key = entry.getKey();

        JsonObject printer = (JsonObject) entry.getValue();

        if (...) {
            printers.remove(key);
        }
    }

    Utils.currentPrinters = printers;

实际上有两个线程调用了这个方法。如果只有一个,则完全没有问题。但是在使用两个线程运行几秒钟后,它崩溃并出现以下异常:

 05-13 12:01:43.168    5739-5739/com.wasp.pos.app E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.util.ConcurrentModificationException
        at com.google.gson.internal.LinkedTreeMap$LinkedTreeMapIterator.nextNode(LinkedTreeMap.java:541)
        at com.google.gson.internal.LinkedTreeMap$EntrySet$1.next(LinkedTreeMap.java:565)
        at com.google.gson.internal.LinkedTreeMap$EntrySet$1.next(LinkedTreeMap.java:563)
        at com.wasp.pos.app.server.PrintersFinder.clearPrinters(PrintersFinder.java:184)
        at com.wasp.pos.app.server.PrintersFinder.access$000(PrintersFinder.java:30)
        at com.wasp.pos.app.server.PrintersFinder$1UpdateListThread.run(PrintersFinder.java:124)
        at android.os.Handler.handleCallback(Handler.java:615)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:153)
        at android.app.ActivityThread.main(ActivityThread.java:4987)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:821)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:584)
        at dalvik.system.NativeStart.main(Native Method)

我真的找不到任何解决这个问题的方法,ConcurrentMap 或 synchronized(打印机)没有解决它。请帮忙。

最佳答案

如前所述,不要从您正在迭代的集合中删除。相反:

Set<String> removed = new TreeSet<String>();
for (Map.Entry<String, ?> entry : Utils.currentPrinters.entrySet()) {

    String key = entry.getKey();

    JsonObject printer = (JsonObject) entry.getValue();

    if (...) {
        removed.add(key);
    }
}
for (String key : removed)
    Utils.currentPrinters.remove(key);

另外两件事:

  • 原始代码中的临时变量“printers”没有任何变化,因为它引用了同一个对象。当然,除非出于某种原因,代码对您来说更清晰......

  • 如果这个方法被多个线程访问...不要!他们在做同样的事情,你将一无所获。同步整个 block 。

关于尝试更新全局变量时出现 java.util.ConcurrentModificationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23627077/

相关文章:

java - 非线程安全行为 - 竞争条件永远不会发生

java - Android:新线程在完成执行后会停止吗?

java - 使用 connectedInstrumentTest 构建 Android 作业不适用于 Jenkins

java - 用于派生查询的 Spring jpa 拦截器

java - 如何正确使用 JPanel 作为其他几个 JPanel 的容器?

java - 如果设备中没有安装truecaller,我们可以使用Truecaller SDK吗?

java - 如果我终止 jUnit 测试会发生什么

java - 为什么 Android 应用程序因 UnsatisfiedLinkError 崩溃?

android - 删除动态创建的 ImageViews Android 之间的空白

java - 无法在多线程中实现同步