java.util.ConcurrentModificationException 在 Android 游戏循环中
java.util.ConcurrentModificationException in Android Game Loop
我正在使用canvas,在屏幕上移动物体,当一个物体击中canvas(x=0)的左侧时,另一个相同类型的物体被实例化,并开始在屏幕上移动。
一切正常,创建了一些对象并开始在屏幕上移动。
在某个时候,我在游戏循环所在的 运行 方法中收到 并发修改异常 ,其中 gameObjs 是一个 ArrayList:
@Override
public void run() {
while(isRunning){
if(!myHolder.getSurface().isValid())
continue;
Canvas canvas = myHolder.lockCanvas();
canvas.drawRect(0,0,canvas.getWidth(), canvas.getHeight(), pWhite);
for(MyGameObject gameObj : gameObjs){
gameObj.move(canvas);
}
myHolder.unlockCanvasAndPost(canvas);
}
}
我试过使用迭代器,但仍然遇到同样的错误。
非常感谢您的帮助。提前致谢!
如果发生这样的事情,Collections.synchronizedList(...) 将无法工作...(抛出 ConcurrentModificationException...)
public class ConcurrentTest {
public static void main(String[] args) {
List<String> things = new ArrayList<>();
Runnable modifyThread = () -> {
while(true) {
for(int k = 0; k < 1000; k++) {
things.add(String.valueOf(k));
}
while(!things.isEmpty()) {
things.remove(0);
}
}
};
Runnable readThread = () -> {
while(true) {
for(String thing : Collections.synchronizedList(things)) {
System.out.println(thing);
}
}
};
new Thread(modifyThread).start();
new Thread(readThread).start();
}
}
尝试在您的代码中找到修改此列表的其他位置。当您遍历集合时,必须有另一个线程在操作集合。
您可以在遍历列表之前获取列表的副本。
例如,在上面的代码中,尝试...
for(String thing : new ArrayList<>(things)) {
...而不是...
for(String thing : Collections.synchronizedList(things)) {
...你将不再得到异常(但这仍然不会是 "correct",如果你 运行 它,你会看到打印出大量空值.. .)
更好的是,将读取循环保持为...
for(String thing : things) {
...但更改列表类型...
List<String> things = new CopyOnWriteArrayList<>();
我正在使用canvas,在屏幕上移动物体,当一个物体击中canvas(x=0)的左侧时,另一个相同类型的物体被实例化,并开始在屏幕上移动。
一切正常,创建了一些对象并开始在屏幕上移动。
在某个时候,我在游戏循环所在的 运行 方法中收到 并发修改异常 ,其中 gameObjs 是一个 ArrayList:
@Override
public void run() {
while(isRunning){
if(!myHolder.getSurface().isValid())
continue;
Canvas canvas = myHolder.lockCanvas();
canvas.drawRect(0,0,canvas.getWidth(), canvas.getHeight(), pWhite);
for(MyGameObject gameObj : gameObjs){
gameObj.move(canvas);
}
myHolder.unlockCanvasAndPost(canvas);
}
}
我试过使用迭代器,但仍然遇到同样的错误。
非常感谢您的帮助。提前致谢!
Collections.synchronizedList(...) 将无法工作...(抛出 ConcurrentModificationException...)
public class ConcurrentTest {
public static void main(String[] args) {
List<String> things = new ArrayList<>();
Runnable modifyThread = () -> {
while(true) {
for(int k = 0; k < 1000; k++) {
things.add(String.valueOf(k));
}
while(!things.isEmpty()) {
things.remove(0);
}
}
};
Runnable readThread = () -> {
while(true) {
for(String thing : Collections.synchronizedList(things)) {
System.out.println(thing);
}
}
};
new Thread(modifyThread).start();
new Thread(readThread).start();
}
}
尝试在您的代码中找到修改此列表的其他位置。当您遍历集合时,必须有另一个线程在操作集合。
您可以在遍历列表之前获取列表的副本。
例如,在上面的代码中,尝试...
for(String thing : new ArrayList<>(things)) {
...而不是...
for(String thing : Collections.synchronizedList(things)) {
...你将不再得到异常(但这仍然不会是 "correct",如果你 运行 它,你会看到打印出大量空值.. .)
更好的是,将读取循环保持为...
for(String thing : things) {
...但更改列表类型...
List<String> things = new CopyOnWriteArrayList<>();