解决 ConcurrentModificationException
我正在编写一个小游戏,屏幕上有很多移动的圆圈。
我正在两个线程中管理圆,如下所示:
public void run() {
int stepCount = 0;
int dx;
int dy;
while (m_threadTrap){
dx = 0;
dy = 0;
synchronized (m_circles) {
for (Iterator<Circle> it = m_circles.iterator(); it.hasNext();){
Circle c = it.next(); //Exception thrown here.
if (c.getDirX() != 0)
if (stepCount % c.getDirX() == 0){
dx = 1;
}
if (c.getDirY() != 0)
if (stepCount % c.getDirY() == 0){
dy = 1;
}
c.move(dx, dy);
}
}
if (stepCount == 150000){
stepCount = 0;
}
stepCount++;
}
}
圆的 ArrayList 中的 m_circles。
以及以下线程:
public void run() {
while (m_threadTrap){
int topPosition;
int bottomPosition;
int leftPosition;
int rightPosition;
ArrayList<Circle> removedCircles = new ArrayList<Circle>();
synchronized (m_circles.getCircles()) {
for (Iterator<Circle> it = m_circles.getCircles().iterator(); it.hasNext();){
Circle c = it.next();
// Some calculation to evaluate which circles should be removed
removedCircles.add(c);
}
}
}
try{
Thread.sleep(25);
}
catch (Exception e) { }
m_circles.getCircles().removeAll(removedCircles);
if (m_circles.getCircles().size() < 30)
m_circles.addNewCircle();
repaint();
}
}
行中收到 ConcurrentModificationException
Circle c = it.next();
我的问题是我在第一个线程中的 。起初,我尝试使用 foreach 循环遍历 ArrayList,这给了我同样的异常。
对这个异常进行了一些研究后,我看到了两种解决方案:
1. 将访问集合的部分放在同步块中。
2.使用集合的Iterator对象。
他们都没有为我解决这个问题。
I am writing a little game which has many circles moving on the screen.
I am managing the circles in two threads as following:
public void run() {
int stepCount = 0;
int dx;
int dy;
while (m_threadTrap){
dx = 0;
dy = 0;
synchronized (m_circles) {
for (Iterator<Circle> it = m_circles.iterator(); it.hasNext();){
Circle c = it.next(); //Exception thrown here.
if (c.getDirX() != 0)
if (stepCount % c.getDirX() == 0){
dx = 1;
}
if (c.getDirY() != 0)
if (stepCount % c.getDirY() == 0){
dy = 1;
}
c.move(dx, dy);
}
}
if (stepCount == 150000){
stepCount = 0;
}
stepCount++;
}
}
m_circles in an ArrayList of Circles.
And the following Thread:
public void run() {
while (m_threadTrap){
int topPosition;
int bottomPosition;
int leftPosition;
int rightPosition;
ArrayList<Circle> removedCircles = new ArrayList<Circle>();
synchronized (m_circles.getCircles()) {
for (Iterator<Circle> it = m_circles.getCircles().iterator(); it.hasNext();){
Circle c = it.next();
// Some calculation to evaluate which circles should be removed
removedCircles.add(c);
}
}
}
try{
Thread.sleep(25);
}
catch (Exception e) { }
m_circles.getCircles().removeAll(removedCircles);
if (m_circles.getCircles().size() < 30)
m_circles.addNewCircle();
repaint();
}
}
My problem is that I get ConcurrentModificationException at the line
Circle c = it.next();
in the first thread. At first I tried going over the ArrayList with a foreach loop and this gave me the same exception.
After researching a bit on this exception I saw two solutions:
1. Putting the part which accesses the collection in a synchronized block.
2. Using the Iterator object of the collection.
Neither of them solved it for me.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
ConcurrentModificationException 意味着您正在迭代一个集合,并且在迭代过程中,某人(当前线程或另一个线程)在不使用
Iterator.remove()
的情况下修改了底层集合。每当您在迭代器上调用操作时,它都会检查基础集合是否未更改。使用 foreach 不会改变任何事情,因为它使用迭代器来执行循环。您的解决方案是:
创建一个新集合:
for (Circle c: new ArrayList(m_circles.getCircles()).iterator()) {
// 一些计算来评估哪些圆应该被删除
删除了Circles.add(c);
}
ConcurrentModificationException means that you are iterating over a collection and, while iterating, someone (the current thread or another one) modified the underlying collection without using
Iterator.remove()
. Whenever you invoke an operation on the Iterator it checks that the underlying collection has not been changed. Using a foreach does not change a thing, since it uses an Iterator to perform the loop.Your solution are:
create a new collection:
for (Circle c: new ArrayList(m_circles.getCircles()).iterator()) {
// Some calculation to evaluate which circles should be removed
removedCircles.add(c);
}
or synchronize both threads on the same object (you synchronize on different objects, therefore it does not do anything) whenever you are modifying or accessing the collection
为了使
synchronized() {}
块有效,对受保护对象的所有访问必须包装在同步块中。您可能忘记包装一些访问权限。另一个“问题”是 ConcurrentModificationException 也可能意味着它是在同一个线程中并发修改的。例如,如果在遍历集合时从集合中删除一个元素,则可能会出现此异常。 (作为例外,您可以通过迭代器本身安全地删除元素)
For a
synchronized() {}
block to be effective, all accesses to the protected objects must be wrapped in synchronized blocks. You probably forgot to wrap some access.Another "gotcha" is that ConcurrentModificationException can also mean that it was concurrently modified in the same thread. For example, if you remove an element from a collection while traversing it, you may get this exception. (As an exception, you can safely remove elements via the iterator itself)