Java TryCatch ConcurrentModificationException捕获30%的时间
我正在使用迭代器从列表中删除超出JPanel边界的投射物。在使用迭代器之前,它不起作用,但对于迭代器,只要我将该方法放入Java TryCatch ConcurrentModificationException捕获30%的时间,java,swing,try-catch,concurrentmodification,Java,Swing,Try Catch,Concurrentmodification,我正在使用迭代器从列表中删除超出JPanel边界的投射物。在使用迭代器之前,它不起作用,但对于迭代器,只要我将该方法放入ConcurrentModificationException的try catch中,它就起作用。代码现在可以工作了,并且成功地从列表中删除了投射物,但是大约30%的时间,捕捉命中并在我的程序中导致口吃。我不知道为什么它只是偶尔捕捉,但在有限的时间内,我的教授能够看到它,他认为这可能是一个同步问题 下面是运行我的程序的循环: private void executeGameLo
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());
}
}
}
}
最后两种方法是我创建投射物的机制:
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());
}
private void(int x,int y)
{
总计++;
if(shots.size()
如果您能深入了解发生这种情况的原因或如何纠正它,我们将不胜感激。您的
for
循环中有一个开放的迭代器(加上额外的迭代器),并且您正在createSproject
中添加值。您需要在快照上使两个块同步
,或者(我的建议)复制快照
,以便从以下位置进行绘图:
List<Projectile> shotsToPaint;
synchronized(shots) { shotsToPaint = [`ImmutableList`][1].copyOf(shots); }
List shotsToPaint;
已同步(快照){shotsToPaint=[`ImmutableList`][1]。复制(快照);}
并在中应用适当的同步。根据性能敏感程度的不同,您可以在shots
上同步整个方法,也可以在shots
上同步,检查大小,在未同步的块中创建新的投射物,然后同步以重新检查列表大小并添加。for循环是问题之一。创建如下循环时:
for (Projectile a : shots) {...}
编译器将其隐式转换为:
for (Iterator<Projectile> i = shots.iterator; i.hasNext();) {
Projectile a = i.next();
...
}
for(迭代器i=shots.Iterator;i.hasNext();){
射弹a=i.next();
...
}
所以总共有两个迭代器。第一个是在显式调用shots.iterator()时创建的,第二个是由for循环中的编译器隐式创建的
ConcurrentModificationException
的一个原因是当其他人在您迭代列表的同时修改列表时。您的教授怀疑存在同步问题,因为通常“其他人”位于不同的线程中,但在本例中,“其他人”是另一个迭代器
编辑:正如chrylis所指出的,还有来自不同线程的干扰。您应该努力防止引起ConcurrentModificationException,而不是捕获它。并且您应该发布堆栈跟踪。FWIW,您有两个主要问题都可能导致ConcurrentModificationException
s。您需要修复我发现的问题和@dnault发现的问题。感谢您的帮助,我不知道循环中有一个隐含的迭代器,正如dnault指出的那样。使用此隐含的迭代器
确实会删除ConcurrentModificationException
问题。然而,我仍然对任何同步都缺乏经验。你能为我指出一个学习如何在这里应用同步的方向吗?@Caboose我手头没有教程,但基本规则是,你需要仔细检查可能从多个线程使用的任何对象的使用情况;为图形操作保留状态的对象是红旗。总是假设它上的任何两个操作都可能被中断,因此在<代码> CureTealPosile < /代码>中,在检查<代码> siz()/<代码>之后,有人可能修改<代码>投注< /代码>,但在<>代码>添加(TEMP)。如果答案是“否”,则可以通过确保两个方法在同一个锁上同步来强制执行此操作。如果您向我们展示的所有方法都在同一个类中,那么只需在update()和createSprojector()的定义中添加一个“synchronized”关键字即可。有关同步的更多信息,请参见此处:
for (Iterator<Projectile> i = shots.iterator; i.hasNext();) {
Projectile a = i.next();
...
}