Java-并发修改异常

标签 java android concurrency timer

我正在摆弄计时器来感受我想要的新游戏。目前,我有使用计时器淡入和淡出的方 block ,当它们完全淡出时,它们会从“Activity 图 block ”列表中删除。我有另一个计时器正在运行,而淡入淡出计时器也可能正在运行,它会在随机位置生成方 block ,每个方 block 都有淡入和淡出。这一切看起来都很顺利,但后端却出了问题。

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

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

在我看来,这似乎是执行此操作的唯一方法,因为我实际上只知道计时器的一种标准方法,并且对此没有太多经验。我想知道是否有更好的方法不会导致此并发异常,和/或解释为什么会发生这种情况。

谢谢!

下面是一些相关代码: (我正在使用 android 图形库,但它并不真正适用于此)

游戏.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);
        }
    }
}

最佳答案

使用迭代器并调用remove():

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

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

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

}

This链接将帮助您了解并发修改异常。

关于Java-并发修改异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30035680/

相关文章:

java - Actor 与线程的定义有何不同?

android - 如何在 tablayout 底部显示 admob 广告

java - 警报管理器有时会在错误的时间触发

java - 使用 ConcurrentHashMap 实现参数化线程安全的延迟初始化缓存(不带 volatile 关键字)

php - 在 MYSQL 中使用 SELECT MAX(id) 而不是在 PHP 中使用 mysql_insert_id() 有多糟糕?

java - 以 ArrayList 作为参数相乘列表元素的方法

java - List<E> 不喜欢我的自定义类

android - 执行动画,然后在动画完成后显示字段 Android

Java循环任务,日期问题

java - GUI编程-定制框架