TryCatch ConcurrentModificationException 捕获`30% 的时间 [英] TryCatch ConcurrentModificationException catching `30% of the time

查看:31
本文介绍了TryCatch ConcurrentModificationException 捕获`30% 的时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using an iterator to remove a projectile from a list if it goes out of the border of my JPanel. Before using the iterator it would not work, but with the iterator it works so long as I put the method into a try-catch for a ConcurrentModificationException. The code now works, and successfully removes the projectile from the list, but about 30% of the time, the catch hits and causes a stutter in my program. I don't know why it only catches sporadically, but in the limited time my professor was able to look at it he thought it may have been a synchronization issue.

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

Here is the loop running my program:

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 处的循环调用.它现在处理更新射弹:

This is called by the loop at panel.update. It handles updating the projectiles for now:

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"); } 
        }

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

These last two method are my mechanism for creating the projectile:

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());
}

任何有关为什么会发生这种情况或如何纠正它的见解将不胜感激.

Any insight about why this is happening or how to rectify it would be greatly appreciated.

推荐答案

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

You have an open Iterator in your for loop (plus the extra Iterator it), and you're adding values in createProjectile. You need to either make both blocks synchronized on shots, or (my recommendation) make a copy of shots to do your drawing from:

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

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

and apply appropriate synchronization in createProjectile. Depending on how performance-sensitive it is, you can either synchronize the whole method on shots or synchronize on shots, check the size, create the new Projectile in an unsynchronized block, and then synchronize to recheck the list size and add.

这篇关于TryCatch ConcurrentModificationException 捕获`30% 的时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆