Java - 并发修改异常

时间:2015-05-04 17:00:14

标签: java android concurrency timer

我正在和计时器搞混,以了解我想到的新游戏。目前,我有使用计时器淡入和淡出的正方形,当它们完全淡出时,它们将从"活动磁贴列表中删除。我有另一个计时器,而淡入淡出计时器也可能正在运行,它在随机位置产生方块,每个都有淡入淡出。这一切看起来都很漂亮,但在后端出现问题。

程序抛出ConcurrentModificationException。我对这些的了解非常有限,但我知道在迭代对象和同时更改对象时会发生这种情况。

这可能发生在我的程序中,可能是两个滴答声同时相遇,它会抛出此异常,但我不知道。

在我脑海中,这似乎是唯一的方法,因为我真的只知道计时器的一种标准方法,并且对此没有多少经验。我想知道是否有更好的方法不会导致这个并发异常,和/或解释为什么会发生这种情况。

谢谢!

以下是一些相关代码: (我使用的是Android图形库,但它并不适用于此)

Game.java:

public Game(Context context) {
    super(context);

    metrics = context.getResources().getDisplayMetrics();
    SCREEN_WIDTH = metrics.widthPixels;
    SCREEN_HEIGHT = metrics.heightPixels;

    spawner = new Spawner();
}


@Override
protected void onDraw(Canvas canvas) {

    for(Tile tile : spawner.activeTiles) {
        //System.out.println("Tile Color: " + tile.getColor());
        canvas.drawRect(tile, tile.getColor());
    }

    try { Thread.sleep(10); }
    catch (InterruptedException e) {}
    invalidate();
}

@Override
public boolean onTouchEvent(MotionEvent e) {

    System.out.println(spawner.activeTiles);

    float x = e.getX();
    float y = e.getY();

    for(Tile tile : spawner.activeTiles) {
        if(tile.contains(x, y) && tile.equals(spawner.activeTiles.get(0))) {
            tile.setBroken(true);
            spawner.activeTiles.remove(tile);
        }
    }

    return true;    
}

Tile.java:

    public Tile(int lifetime) {
    super();
    this.lifetime = lifetime;
    TILE_WIDTH = (int) Game.SCREEN_WIDTH / 10;
    TILE_HEIGHT = (int) Game.SCREEN_HEIGHT / 15;

    tileColor = new Paint();
    tileColor.setColor(Color.argb(0, 255, 0, 0));
    placeTile();
}

private void placeTile() {
    float screenWidth = Game.SCREEN_WIDTH;
    float screenHeight = Game.SCREEN_HEIGHT;

    Random random = new Random();
    top = random.nextInt((int) screenHeight - (TILE_HEIGHT * 2)) + 10;
    left = random.nextInt((int) screenWidth - (TILE_WIDTH * 2)) + 10;
    bottom = top + TILE_HEIGHT;
    right = left + TILE_WIDTH;

    fadeIn(5);  
}

private void fadeIn(final int speed) {
    if(tileColor != null) {
        final Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {

            @Override
            public void run() {
                int alpha = tileColor.getAlpha();

                if(alpha < 255) {
                    if(alpha + 5 > 255) tileColor.setAlpha(255);
                    else tileColor.setAlpha(alpha + 5);
                } else {
                    timer.cancel();
                    fadeOut(speed);
                }
            }   

        }, 50, speed);                  
    }
}
private void fadeOut(int speed) {
    if(tileColor != null) {
        final Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {

            @Override
            public void run() {
                int alpha = tileColor.getAlpha();

                if(alpha > 0 && !broken) {
                    if(alpha - 5 < 0) tileColor.setAlpha(0);
                    else tileColor.setAlpha(alpha - 5);
                } else {
                    failed = true;
                    timer.cancel();
                }
            }   

        }, lifetime, speed);    
    }
}

Spawner.java:

public List<Tile> activeTiles = new ArrayList<Tile>();

public long tileDelay = 500;

public Spawner() {
    start();
}

private void start() {

    Timer timer = new Timer();  
    timer.schedule(new TimerTask() {

        @Override
        public void run() {
            removeFailedTiles();

            activeTiles.add(new Tile(1000));    
        }

    }, 0, tileDelay);
}

private void removeFailedTiles() {
    for(Tile tile : activeTiles) {
        if(tile.isFailed()) {
            activeTiles.remove(tile);
        }
    }
}

1 个答案:

答案 0 :(得分:3)

使用Iterator并致电remove()

Iterator<Tile > iter = activeTiles.iterator();

while (iter.hasNext()) {
    Tile tile= iter.next();

    if(tile.isFailed()) 
        iter.remove();

}

This链接将帮助您了解并发修改例外。