[英]Iterating through arraylist in one class, while adding an element in other class
i'm getting a concurrentmodification exception, the problem is that i'm iterating through an arrayList and drawing and updating the sprites in the arraylist, while adding new sprites in another java class. 我收到并发修改异常,问题是我要遍历arrayList并绘制和更新arraylist中的精灵,同时在另一个java类中添加新的精灵。
public abstract class Scene
{
ArrayList<UIElement> uiElements = new ArrayList<>();
ArrayList<GameObject> sprites = new ArrayList<>();
public ArrayList<GameObject> getSprites()
{
return sprites;
}
public ArrayList<UIElement> getUiElements()
{
return uiElements;
}
public abstract void load();
public abstract void unload();
public void update()
{
sprites.forEach(GameObject::update);
uiElements.forEach(UIElement::update);
}
public void draw(Graphics2D g2)
{
sprites.forEach(e -> e.draw(g2));
uiElements.forEach(e -> e.draw(g2));
}
}
so these are the iterating methods in the java class named Scene.java 所以这些是名为Scene.java的Java类中的迭代方法
public void onButtonsEvent(WiimoteButtonsEvent wiimoteButtonsEvent)
{
// shoot firebolt when button b is held
if( wiimoteButtonsEvent.isButtonBHeld())
{
if(updateIndexTwo % UPDATE_SPEED == 0)
{
Vector2D fireboltVector = new Vector2D(vector.getX()+SPRITE_WIDTH/2, vector.getY(), crossHair.getX() + CH_SIZE/2, crossHair.getY() + CH_SIZE/2);
Firebolt firebolt = new Firebolt(fireboltVector, damage, color, scene);
scene.getSprites().add(firebolt);
updateIndexTwo = 0;
}
updateIndexTwo++;
}
}
this is the code where the Firebolt(sprite) will be added to the sprites arraylist in Scene 这是将Firebolt(sprite)添加到Scene中的sprites arraylist中的代码
i'm getting a concurrentmodification exception, the problem is that i'm iterating through an arrayList and drawing and updating the sprites in the arraylist, while adding new sprites in another java class.
我收到并发修改异常,问题是我要遍历arrayList并绘制和更新arraylist中的精灵,同时在另一个java类中添加新的精灵。
The basic solution is fairly simple: don't do that. 基本解决方案非常简单:请勿这样做。 It is an intentional design feature that if an
ArrayList
is structurally modified, then any iterators over that list that were obtained prior to the modification are invalidated; 一个有意设计的功能是,如果对
ArrayList
进行了结构修改,则在修改之前在该列表上获得的所有迭代器都将无效; further use of them causes ConcurrentModificationException
to be thrown. 进一步使用它们会引发
ConcurrentModificationException
。 This happens whether you're using Iterator
s directly, using an enhanced for
loop, or using forEach()
. 无论您是直接使用
Iterator
,使用增强的for
循环还是使用forEach()
,都会发生这种情况。 The other basic collections classes ( LinkedList
, HashSet
, etc.) all work the same way. 其他基本集合类(
LinkedList
, HashSet
等)都以相同的方式工作。
If indeed you must accommodate the collection being modified without breaking an ongoing iteration over it, then you need a collection class that accomodates such activity. 如果确实必须在不中断正在进行的迭代的情况下容纳要修改的集合,那么您需要一个容纳此类活动的集合类。 For example, you could consider
ConcurrentLinkedDeque
, or one of the other collections from java.util.concurrent
. 例如,您可以考虑使用
ConcurrentLinkedDeque
或java.util.concurrent
中的其他集合之一。 It is possible to write your own, but it's tricky, and why do that when there are existing classes in the standard library that will serve? 可以编写自己的代码,但这很棘手,为什么在标准库中已有可以使用的类的情况下这样做呢?
Note also that although a solution can be found in java.util.concurrent, the problem does not depend on multiple threads being involved. 还要注意,尽管可以在java.util.concurrent中找到解决方案,但问题并不取决于所涉及的多个线程。 In fact, if you do have multiple threads then using one of the concurrent collections serves a dual purpose: it also ensures consistent operations on the collection without need of external synchronization.
实际上,如果您确实有多个线程,那么使用并发集合之一可以达到双重目的:它还可以确保对集合进行一致的操作而无需外部同步。 If by any chance you were previously accessing the list from multiple threads without proper synchronization then getting the CME was a lucky break -- you might instead have just gotten silent malfunction.
如果您有机会在没有适当同步的情况下从多个线程访问列表,那么获得CME是一个幸运的休息-您可能只是陷入了静默故障。
Look at an existing thread safe class such as ArrayBlockingQueue. 查看现有的线程安全类,例如ArrayBlockingQueue。 You can wrap your ArrayList in synchronization code but it's easier to use a data structure that already does what you want.
您可以将ArrayList包装在同步代码中,但是使用已经可以完成所需功能的数据结构会更容易。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.