我目前正在研究一个java轰炸机人游戏,游戏工作正常,但我确实有一个并发修改异常,反复抛出。
在我的游戏中,我有两个玩家,每个玩家都有自己的线程,使用计时器以恒定的60fps运行(thread.run()
)。我尝试在每个玩家运行方法结束后麻烦线程运行后重新绘制运行。
方法1:
public void loop() {
if (!gameover) {
player1_thread.run(); //run player 1 thread
player2_thread.run(); //run player 2 thread
gui.repaint() //repaint panel
}
}
方法2:
public class Player extends Character { //Character implements Runnable
...
@Override
public void run() {
play();
...
game.render();
}
}
这两种方法都抛出了预期的并发修改,所以如何避免错误,只需执行以下操作:
player1.run(); //call the run method of each player class
player2.run();
这给了玩家1一个优势。
编辑:
方法4:
import java.util.Timer
public class Player extends Character { //Character implements Runnable
private Timer gameTimer
@Ovveride
public void run() {
gameTimer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
play();
...
game.render();
}
}, 0, 1000/60);
}
}
public class Game extends AbstractGame {
private void init() {
...
Thread player1_Thread = new Thread(player1);
Thread player2_Thread = new Thread(player2);
gui = new GameGraphics(this); //subclass of JPanel
player1_thread.start();
player2_thread.start();
}
/* this method is called at a constant 60fps(like the player timer) in the main game timer in my abstract game class */
public void gameLoop(){
if(!gameover){
render();
...
}
}
}
这也引发了异常
错误:调用run()将使用主线程执行指令。
正确:调用player1.start()来启动一个新线程,以便在新启动的线程中执行run(){...}。
如果Player
是Thread
的子类,你可以用.start()
启动它,但是不要在循环中启动线程。你只需要启动一个线程,之后它将一直运行直到该类中的run方法完成,很可能你想用循环编写一个run方法,所以它一直运行到你停止它为止。如果你想用一个线程运行游戏,你可以实现Runnable
,并做你现在做的事情,在循环中调用run()
。那时只有一个主线程。
通过在线程对象上调用run,你不是在启动一个线程,它只是在那个对象中调用run方法。
我认为最好的办法是,只需一个线程就可以使用模型中的数据更新paint。从播放器线程更改此模型中的数据。