如何处理ConcurrentModificationException

时间:2012-06-19 04:15:10

标签: java for-loop runnable concurrentmodification

我从冷却计时器中得到一个ConcurrentModificationException。我使用线程每秒减少值,如下所示:

public class CoolDownTimer implements Runnable {
    @Override
    public void run() {
        for (String s : playerCooldowns.keySet()) {
            playerCooldowns.put(s, playerCooldowns.get(s) - 20);
            if (playerCooldowns.get(s) <= 0) {
                playerCooldowns.remove(s);
            }
        }
    }

}

因此每秒钟它应该将每个玩家的冷却时间减少20,但问题是我在运行程序时每隔几个小时就会获得一次CME,特别是当很多人在线时。如何使它如果仍在修改列表,它将等到当前操作完成并创建一种修改队列?谢谢!这是堆栈跟踪:

2012-06-18 20:59:05 [WARNING] Task of 'SurvivorsClasses' generated an exception
java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:839)
at java.util.HashMap$KeyIterator.next(HashMap.java:874)
at me.zachoooo.survivorclasses.CoolDownManager$CoolDownTimer.run(CoolDownManager.java:13)
at org.bukkit.craftbukkit.scheduler.CraftScheduler.mainThreadHeartbeat(CraftScheduler.java:126)
at net.minecraft.server.MinecraftServer.w(MinecraftServer.java:533)
at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:459)

第13行是for循环的开始......

3 个答案:

答案 0 :(得分:3)

使用foreach循环时无法修改集合。

可以迭代Map.entrySet()并做你需要的一切:

public void run() {
    for (Iterator<Map.Entry<String,Integer>> i = playerCooldowns.entrySet().iterator(); i.hasNext();) {
        Map.Entry<String,Integer> entry = i.next();
        entry.setValue(entry.getValue() - 20); // update via the Map.Entry
        if (entry.getValue() <= 0) {
            i.remove(); // remove via the iterator
        }
    }
}

答案 1 :(得分:1)

当您尝试修改ConcurrentModificationException的内容时,Collection会被Iterating抛出,同时The iterators returned by all of this class's "collection view methods" are fail-fast: if the map is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove method, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future. Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. 通过它。

请阅读thisthis以获取更多讨论。

documentation中明确提到了有时候它可能会对你有用的原因。

{{1}}

答案 2 :(得分:0)

运行期间

Unlike ArrayCollections编译时间不是期间仅选中 时间,这就是无法在循环中修改像put()或remove()这样的Collection的原因。