如果射弹超出JPanel的边界,我正在使用迭代器将其从列表中删除。在使用迭代器之前,它将无法正常工作,但是只要使用迭代器,只要我将方法放入ConcurrentModificationException的try-catch中,它就可以工作。该代码现在可以正常工作,并且可以成功地将弹丸从列表中删除,但是大约有30%的时间,渔获物击中并导致程序结结。我不知道为什么它只会偶尔出现,但是在有限的时间内,我的教授能够看到它,他认为这可能是同步问题。

这是运行我的程序的循环:

private void executeGameLoop()
        {

            long nextFrameStart = System.nanoTime();
            while(panel.getRunning())
            {
                do
                {
                    panel.repaint();
                    nextFrameStart += FRAME_PERIOD;
                } while(nextFrameStart < System.nanoTime());

                long remaining = nextFrameStart - System.nanoTime();
                panel.update();

                if (remaining > 0)
                {
                    try
                    {
                        Thread.sleep(remaining / 1000000);
                    }
                    catch(Throwable e)
                    {
                        System.out.println(e.getMessage());
                    }
                }
            }
        }


这由panel.update处的循环调用。它现在可以处理弹丸的更新:

public void update()
        {
            randX = (int)((Math.random() * getWidth()) - (int)(Math.random() * getWidth()));
            randY = (int)((Math.random() * getHeight()) - (int)(Math.random() * getHeight()));

            int sizeX;
            int sizeY;

            try
            {
                Iterator<Projectile> it = shots.iterator();
                for(Projectile a : shots)
                {
                    if(!a.equals(null))
                    {
                        sizeX = a.getDisplayX();
                        sizeY = a.getDisplayX();

                        if((!checkCoords((int)a.getX(), (int)a.getY(), sizeX, sizeY)) && a.hasTarget())
                        {
                            a = null;
                            if(it.next().equals(null));
                                it.remove();
                        }

                        else if(a.hasTarget())
                        {
                            a.update();
                        }
                    }
                }
            }
            catch (ConcurrentModificationException e){ System.out.println(e.getMessage() + " Catch"); }
        }


最后两种方法是我创建弹丸的机制:

private void createProjectile(int x, int y)
{
    total++;
    if(shots.size() < shotCount)
    {
        Projectile temp = new Projectile(randX, randY);
        temp.setTarget((x + temp.getSprite().getDisplayImg().getWidth() / 8),
                        (y - temp.getSprite().getDisplayImg().getHeight() / 8));
        temp.setHasTarget(true);
        shots.add(temp);
        msg("Target: (" + x + ", " + y + ")");
    }
}

@Override
public void mouseClicked(MouseEvent e)
{
    createProjectile(e.getX(), e.getY());
}


对于为什么会发生或如何纠正它的任何见解将不胜感激。

最佳答案

您在Iterator循环中有一个打开的for(加上额外的Iterator it),并且正在createProjectile中添加值。您需要在synchronized上制作两个块shots,或(我的建议)制作一份shots的副本,以便从以下位置进行绘图:

List<Projectile> shotsToPaint;
synchronized(shots) { shotsToPaint = [`ImmutableList`][1].copyOf(shots); }


并在createProjectile中应用适当的同步。根据对性能的敏感程度,您可以在shots上同步整个方法,也可以在shots上同步,检查大小,在未同步的块中创建新的Projectile,然后进行同步以重新检查列表大小并添加。

08-03 13:04