清除数组时出现ConcurrentModificationException

时间:2014-07-08 15:11:29

标签: java arraylist

清除数组时出现ConcurrentModificationException。

package net.minecraft.client.gui;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import net.minecraft.block.Block;
import net.minecraft.block.Xray;
import net.minecraft.client.Minecraft;

import org.lwjgl.opengl.GL11;

public class GuiHub extends GuiScreen{
    static List<GuiInterface> components = new ArrayList<GuiInterface>();
    static FontRenderer fontRenderer;
    static Xray xrayManager;

    public GuiHub(){
        this.components.clear();
        xrayManager = new Xray();
        //Color format: 0xAARRGGBB <-- 
        //Transparent: 0x80RRGGBB
        //Solid: 0xFFRRGGBB
        GuiFrameComponent world = new GuiFrameComponent("World" , 10, 10);
        GuiFrameComponent player = new GuiFrameComponent("Player" , 130, 10);
        GuiFrameBindComponent bindings = new GuiFrameBindComponent("Binds Explorer", 210, 10);
        GuiFrameComponentButton xray = new GuiFrameComponentButton("Xray", false);
        GuiFrameComponentButton fullbright = new GuiFrameComponentButton("Fullbright", false);
        GuiFrameComponentButton day = new GuiFrameComponentButton("Always Day", false);
        GuiFrameComponentButton fly = new GuiFrameComponentButton("Fly", false);
        GuiFrameComponentButton nofall = new GuiFrameComponentButton("NoFall", false);
        GuiFrameComponentButton spider = new GuiFrameComponentButton("Spider Mode", false);
        GuiFrameComponentButton blockreach = new GuiFrameComponentButton("Block Reach", false);
        GuiFrameComponentButton noswing = new GuiFrameComponentButton("No Swing", false);
        //World
        world.addComponent(xray);
        world.addComponent(fullbright);
        world.addComponent(day);
        //Player
        player.addComponent(fly);
        player.addComponent(spider);
        player.addComponent(nofall);
        player.addComponent(blockreach);
        player.addComponent(noswing);

        addComponent(player);
        addComponent(world);

        //addComponent(bindings);

        xrayManager.loadFromStorage();
        xrayManager.addBlock(14);
        xrayManager.addBlock(15);
        xrayManager.addBlock(16);
        xrayManager.addBlock(21);
        xrayManager.addBlock(56);
        xrayManager.addBlock(129);
        xrayManager.addBlock(73);



    }

    public static void addComponent(GuiInterface component){
        components.add(component);
    }

    public void drawScreen(int par1, int par2, float par3) {
        super.drawScreen(par1, par2, par3);

        for(GuiInterface component : components){
            component.drawGuiComponent(par1, par2);
        }
    }

    public void mouseClicked(int par1, int par2, int par3){
        super.mouseClicked(par1, par2, par3);
        for(GuiInterface component : components){
            component.onGuiComponentClicked(par1, par2, par3);
        }
    }

    public void mouseMovedOrUp(int par1, int par2, int par3){
        super.mouseMovedOrUp(par1, par2, par3);
        for(GuiInterface component : components){
            component.onGuiMouseMovedOrUp(par1, par2, par3);
        }
    }

    public boolean doesGuiPauseGame()
    {
        return false;
    }

    public void setMinecraft(Minecraft mc){
        this.mc = mc;
    }

    public void setFontRenderer(FontRenderer fontRenderer) {
        this.fontRenderer = fontRenderer;   
    }

    public static FontRenderer getFontRenderer(){
        return fontRenderer;
    }

    public static Minecraft getMinecraft() {
        return mc;
    }

    public static Xray getXrayManager() {
        return xrayManager;
    }

    public static void setOnTop(GuiInterface component) {
        components.clear();
    }


}

如您所见,drawScreen基本上遍历组件ArrayList。我假设当它尝试访问我的组件ArrayList中的元素时抛出此并发修改异常。我已经尝试了各种方法来解决这个问题,包括:

  • 添加一个shouldRender布尔值。在清除组件ArrayList之前将其设置为false,然后在清除组件arrayList时将其设置为true,如下所示:

    public static void setOnTop(GuiInterface component){     shouldRender = false;     components.clear();     shouldRender = true; }

我拥有它以便它应该是真实的迭代和绘制组件。

这是StackTrace:

此位由游戏API生成 - &gt;

net.minecraft.util.ReportedException: Updating screen events
    at net.minecraft.client.Minecraft.runTick(Minecraft.java:1696) ~[bin/:?]
    at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:995) ~[bin/:?]
    at net.minecraft.client.Minecraft.run(Minecraft.java:911) [bin/:?]
    at net.minecraft.client.main.Main.main(Main.java:109) [bin/:?]
    at Start.main(Start.java:11) [bin/:?]


Not generated by the game API -->
Caused by: java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source) ~[?:1.8.0_05]
    at java.util.ArrayList$Itr.next(Unknown Source) ~[?:1.8.0_05]
    at net.minecraft.client.gui.GuiHub.mouseClicked(GuiHub.java:81) ~[bin/:?]
    at net.minecraft.client.gui.GuiScreen.handleMouseInput(GuiScreen.java:324) ~[bin/:?]
    at net.minecraft.client.gui.GuiScreen.handleInput(GuiScreen.java:288) ~[bin/:?]
    at net.minecraft.client.Minecraft.runTick(Minecraft.java:1682) ~[bin/:?]
    ... 4 more

1 个答案:

答案 0 :(得分:3)

ConcurrentModificationException告诉您在尝试迭代列表时修改了列表。

您可以通过多种方法避免这种情况,包括:

  • 使用线程同步确保另一个线程在迭代时不会尝试修改列表。
  • 使用java.util.concurrent.CopyOnWriteArrayList。修改后,任何现有的迭代器都会继续处理旧列表。