我没有使用线程,但是我不断收到错误消息:
“线程“ AWT-EventQueue-0”中的异常java.util.ConcurrentModificationException”
这是我的代码:
@Override
public void paint(Graphics g) {
for(Rectangles emp: shapes.list) {
//Loop through all rectangle objects
for(int[] temp: emp.arr) {
//Loop through each objects array
g.drawRect(temp[0], temp[1], 20, 20);
g.drawRect(20, 20, 20, 20);
}
}
}
还有一个来自不同类的方法,该方法非常接近paint方法,一遍又一遍地执行,这可能会引起问题。
public class Shapes {
LinkedList<Rectangles> list = new LinkedList<Rectangles>();
Random rand = new Random();
void newshape() {
int shape = rand.nextInt(7);
switch(shape) {
case 0:
list.add(makeSquare());
break;
case 1:
list.add(makeLine());
break;
case 2:
list.add(makeTShape());
break;
case 3:
list.add(makeLShape());
break;
case 4:
list.add(makeJShape());
break;
case 5:
list.add(makeZShape());
break;
case 6:
list.add(makeSShape());
break;
}
}
我正在使用Notch游戏循环,如果自上次制作新形状以来已过一秒钟,则tick()方法将调用newshape()方法。然后调用paint方法。
public void run(Game game) {
while(true) {
lastshapemake = System.nanoTime();
long lastTime = System.nanoTime();
double Target_FPS = 60.0;
double ns = 1000000000 / Target_FPS;
double delta = 0;
while(running) {
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while(delta >= 1) {
tick();
delta--;
}
if(running) {
game.repaint();
}
}
}
}
答案 0 :(得分:2)
问题是,即使您没有意识到,您也正在使用多个线程:
Swing(以及其中的大多数GUI框架)都是单线程的,这意味着只有一个线程可以操作GUI以及该GUI依赖的任何数据。
请参阅:Why is Swing threading model considered wrong and how should it be?
AggregateIterable<Document> findIterable = tripsCollection.aggregate(
Arrays.asList(
new Document("$match", new Document("busId", busId)),
new Document("$unwind", "$location"),
new Document("$sort", new Document("location.position", -1)),
new Document("$group",
new Document("_id", "$_id")
.append("driverId", new Document("$first","$driverId"))
.append("busId", new Document("$first","$busId"))
.append("startTime", new Document("$first","$startTime"))
.append("location", new Document("$push","$location"))
),
new Document("$sort", new Document("startTime", -1))
)
);
方法不会立即绘制;它将一个事件放到事件队列中,当该事件被Swing线程拾取后,它将执行您的重绘代码。
在您尚未发布的repaint
方法期间,您正在更新要在tick
方法中迭代的相同列表,并且由于paint
方法有时会运行与您的paint
方法完全同时,这会导致ConcurrentModificationExceptions。
有两种解决方法。
tick
或EventQueue.invokeLater
在Swing线程上运行所有内容(可以这样安排javax.swing.Timer
方法)tick
方法复制列表。但是,由于使用多个线程,除非采取特殊预防措施,否则可能导致数据争用。您可以使用paint
代替普通的CopyOnWriteArrayList
,也可以使用ArrayList
将普通列表变成一个列表,然后将一个线程中的更改安全地发布到另一个线程中。答案 1 :(得分:0)
ConcurrentModificationException与线程无关。
这意味着:在以下时间轴上,我们位于点'Z':
请注意,您需要在进入for (Type elem : someCollection)
块后创建一个迭代器,并在每次循环循环时都对该迭代器调用next
操作。
从您的代码中无法得知修改发生的位置(您没有这样做;在for循环中像collection.remove(x)这样简单的事情可能会导致ConcurrentModificationException
,但您不要在您粘贴的代码段中执行此操作。
请注意,即使您认为自己做不到,也可以使用swing创建多个线程。因此,如果该代码段确实是您所拥有的,那么将涉及另一个线程,并且它们正在修改shapes
或shapes
中的一项。