Java 并发修改异常,无法解决

Java 并发修改异常,无法解决,java,android,Java,Android,似乎无论我做什么,我都得到了并发修改异常。我做了一些研究,据我所知,当你试图编辑一个列表,同时在其中进行迭代时,会出现这种异常。但我还是不知道到底是什么原因造成的。所以我希望一些更有经验的人能帮我找出哪里出了问题。这是我的密码 package com.gametest; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import android.app.Activity; import

似乎无论我做什么,我都得到了并发修改异常。我做了一些研究,据我所知,当你试图编辑一个列表,同时在其中进行迭代时,会出现这种异常。但我还是不知道到底是什么原因造成的。所以我希望一些更有经验的人能帮我找出哪里出了问题。这是我的密码

package com.gametest;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;

public class GameSurfaceView extends Activity implements OnTouchListener {


    double ran;
    int touchX, touchY, screenWidth, screenHeight, objX, objY;
    static boolean canUpdate;
    static int enemyCount;
    static MyView v;
    static Bitmap orb, explosion;
    static List<Sprite> enemiesList = new ArrayList<Sprite>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        v = new MyView(this);
        v.setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent me) {
                touchX = (int) me.getX();
                touchY = (int) me.getY();
                for (Sprite sprite : enemiesList) {
                    sprite.checkTouch(touchX, touchY);
                }

                return true;
            }
        });
        canUpdate = true;
        ran = 0;
        orb = BitmapFactory.decodeResource(getResources(), R.drawable.blue_orb);
        explosion = BitmapFactory.decodeResource(getResources(), R.drawable.explosion);
        createEnemies();
        setContentView(v);
    }

    private synchronized void createEnemies() {
        if (enemyCount < 5) {
            screenWidth = v.getWidth();
            screenHeight = v.getHeight();
            int listLength = enemiesList.size();
            enemiesList.add(new Sprite(v, orb, explosion, screenWidth, screenHeight, listLength));
            enemyCount = enemyCount + 1;
        }
    }

    public static synchronized void checkECount(int id) {
        canUpdate = false;
        enemyCount = enemyCount - 1;
        enemiesList.remove(id);
        int index = 0;
        Iterator<Sprite> itr = enemiesList.iterator();
          while(itr.hasNext()) {
              Sprite s = itr.next();
                s.ID = index;
                index++; 
          }
        canUpdate = true;

    }

    @Override
    protected void onPause() {
        super.onPause();
        v.pause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        v.resume();
    }

    public class MyView extends SurfaceView implements Runnable {

        Thread t = null;
        SurfaceHolder holder;
        boolean isItOk = false;

        public MyView(Context context) {
            super(context);
            holder = getHolder();

        }

        @Override
        public void run() {
            while (isItOk == true) {
                if (!holder.getSurface().isValid()) {
                    continue;
                }
                Canvas c = holder.lockCanvas();
                if(canUpdate){
                canvas_draw(c);
                }
                holder.unlockCanvasAndPost(c);

            }

        }

        protected synchronized void canvas_draw(Canvas canvas) {
            canvas.drawARGB(255, 50, 10, 10);
            String ranString = Integer.toString(screenHeight);
            ran = Math.random() * 5;
            if (ran > 3) {
                createEnemies();
            }

            Paint paint = new Paint();
            paint.setColor(Color.BLACK);
            paint.setTextSize(15);
            canvas.drawText(ranString, 10, screenHeight - 25, paint);
            for (Sprite sprite : enemiesList) {
                sprite.sprite_draw(canvas);
            }
        }

        public void pause() {
            isItOk = false;
            while (true) {
                try {
                    t.join();
                } catch (InterruptedException e) {

                }
                break;
            }
            t = null;
        }

        public void resume() {
            isItOk = true;
            t = new Thread(this);
            t.start();
        }

    }

    @Override
    public boolean onTouch(View arg0, MotionEvent arg1) {
        // TODO Auto-generated method stub
        return false;
    }

}

问题在于,您可能正在修改“enemiesList”(例如,删除/添加元素),而此时列表正在此处编辑:

for (Sprite s : enemiesList) {
        s.ID = index;
        index++;
}
尝试同步该方法并查看发生了什么(以及将元素添加到列表中的方法):

事实上,我在这里看到了一个潜在的灾难,当“CreateEquires”被调用时,尝试一下,看看会发生什么

希望这有助于


问候

这看起来像是您的问题:

for (Sprite s : enemiesList) {
        s.ID = index;
        index++;
    }
在遍历Sprite类时修改该类中的变量会引发异常。尝试按如下方式声明已同步的方法:

protected synchronized void canvas_draw(Canvas canvas) {

或者使用。

如果列表中的遍历操作远远多于变异操作,则可能需要使用。它有一个快照样式的迭代器,允许您在列表中进行迭代,即使同时列表正在更改。不过,请注意,正如名称所示,每次对底层数组进行更改时,它都会创建一个全新的副本。也就是说,如果更改太多,可能会影响性能。

堆栈跟踪在哪里?超过160行代码,但没有显示问题在哪里。您应该生成一个简短但完整的示例来演示该问题,并包括异常详细信息,包括堆栈跟踪。感谢您的回答,我按照您所说的做了,将canvas_draw更改为synchronized,并使用迭代器而不是for循环,但我仍然得到相同的结果。正如其他人对您的问题发表的评论一样,请发布错误的stacktrace。我不能,评论太长了,stackoverflow在8个小时内不会让我回答我自己的问题。DERP,很抱歉我是个智障。我把代码更新到了我现在的状态,我还添加了logcat。谢谢你的回答。我尝试将其更改为synchronized,但没有运气:(您还可以详细说明CreateEquaries方法的潜在灾难吗?当然,synchronized不仅包括checkECount,还包括“CreateEquaries”或任何其他可能修改列表“enemiesList”的方法……问题是,您在获取该列表时正在添加/删除元素。。。
for (Sprite s : enemiesList) {
        s.ID = index;
        index++;
    }
protected synchronized void canvas_draw(Canvas canvas) {