Java 正在获取并发修改操作异常。问题在哪里?(代码)
我正在用Java编写一个简单的游戏。以下是主要代码:Java 正在获取并发修改操作异常。问题在哪里?(代码),java,swing,concurrentmodification,Java,Swing,Concurrentmodification,我正在用Java编写一个简单的游戏。以下是主要代码: public class MainPanel extends JPanel { private Player player = new Player(100, 100, 3, 3); private Point2D targetPoint = new Point2D.Float(130, 350); //Pos on begin private ArrayList<Beam> beams = new Arr
public class MainPanel extends JPanel {
private Player player = new Player(100, 100, 3, 3);
private Point2D targetPoint = new Point2D.Float(130, 350); //Pos on begin
private ArrayList<Beam> beams = new ArrayList<Beam>();
public MainPanel() {
setPreferredSize(new Dimension(300, 400));
addMouseMotionListener(new MouseMotionHandler());
//Add shortcuts
makeShortcut("player.BM1", "F1", new SetBeamModeAction(1));
makeShortcut("player.BM2", "F2", new SetBeamModeAction(2));
//Start threads
Thread t = new Thread(new PlayerMoveRunnable());
t.start();
Thread t2 = new Thread(new PlayerShootRunnable());
t2.start();
}
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.setColor(Color.BLACK);
g2.fillRect(0, 0, 300, 400);
//Draw player
g2.drawImage(player.getImage(), (int)player.getX(), (int)player.getY(), null);
//Draw beams
for (Beam beam : beams) {
g2.drawImage(beam.getImage(), (int)beam.getX(), (int)beam.getY(), null);
}
}
//Thread running all the time
private class PlayerMoveRunnable implements Runnable {
public void run() {
try {
while (true) {
player.moveToPoint(targetPoint);
repaint();
Thread.sleep(15);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//Thread working all the time
private class PlayerShootRunnable implements Runnable {
public void run() {
try {
while (true) {
//Choose which beam to shoot (depends on set mode)
Thread t;
switch (player.getBeamMode()) {
case 1:
t = new Thread(new BeamMoveRunnable(new Beam1(player.getX()+18, player.getY(), 0, -15)));
break;
case 2:
t = new Thread(new BeamMoveRunnable(new Beam2(player.getX()+18, player.getY(), 0, -30)));
break;
default:
t = null;
break;
}
t.start();
Thread.sleep(200);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private class BeamMoveRunnable implements Runnable {
private Beam beam;
public BeamMoveRunnable(Beam beam) {
this.beam = beam;
}
public void run() {
Beam beam = this.beam;
beams.add(beam);
try {
while (true) {
if (beam.getY() <= 0) {
beams.remove(beam);
break;
}
beam.move();
repaint();
Thread.sleep(20);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
等等
问题出在哪里?我知道ConcurrentModificationException是什么意思,但我不知道这里的问题出在哪里。。也许我应该做一些同步。如果是,请显示在线程
BeamMoveRunnable
(包装此Runnable
对象的线程)中修改数组列表beams
的位置,同时在方法paintComponent
中对其进行迭代。这就是异常的原因。在迭代集合时,您正在修改另一个线程中的梁列表,例如beammoverunable
为每个对象创建线程是非常浪费的,而且很难管理
我建议您有一个线程,它定期调用每个梁上的方法来移动。我建议您不要在绘制梁时添加或删除梁,这样您就不必同步对集合的访问。在
paintComponent
中迭代梁之前,请创建集合的副本并使用副本进行迭代。顺便说一句,您的PlayerShootRunnable循环将永远存在。每200毫秒,它将创建一个新的BeamMoveRunnable线程,该线程也将永远运行。你每秒创建5个新线程,但没有一个线程会退出。当任何梁到达0或更大的位置时,循环中断,线程结束。是的,公平点。对不起,我错过了。仍然看起来像是大量的线程搅动,伊姆霍。好的,所以我将改变它,并作出一个线程,将移动每个梁。但我认为它不会有任何帮助,因为即使这样,线程也有可能在集合上循环并删除一个元素,而paint方法将尝试绘制它。。那么如何预防呢?这就是为什么我说,不要移除任何元素。您只能绘制paintComponent
中可见的元素,而不是删除它们。但这不会影响应用程序的性能吗?或者不会抛出堆栈溢出等异常?每200米自动添加一个新的光束,所以在几分钟的游戏后,会有很多光束。我明白了,你有一个射击游戏。在这种情况下,您需要维护一个集合。我建议您使用事件线程来移动梁,或者您的梁更新线程为GUI线程提供集合的副本,或者您在迭代和更新时同步集合(这不如仅使用我怀疑的事件线程好)。是的,最后一个解决方案是最好的。我使用了它,没有发现任何问题(移除也一样)。再次感谢
Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:819)
at java.util.ArrayList$Itr.next(ArrayList.java:791)
at spacecommander.MainPanel.paintComponent(MainPanel.java:53)
at javax.swing.JComponent.paint(JComponent.java:1054)