我写了一个 Java ME 益智游戏。我这样编写代码:有一个线程在应用程序启动时启动,一旦游戏开始,就会有第二个线程在无限循环中运行——主游戏循环。有一次,第二个线程看起来像这样:
public void run() {
init();
while (shouldIRun) {
updateGameState();
checkUserInput();
updateGameScreen(getGraphics());
this.flushGraphics();
}
}
迷人的。这个线程只是运行并运行,直到我想杀死它,当我将 boolean 值
shouldIRun
设置为 false 时,它就会优雅地退出。但后来我意识到我想要更多。该游戏是一款益智游戏,玩家可能会做出错误的 Action 然后卡住。发生这种情况时,他们可以启动一个表单并选择“重新启动级别”选项。然后设置一个标志
restartLevel
,当无限循环进入 updateGameState()
方法时,关卡重新启动。但这对我来说就像一场赌博——我不想开始更改主循环中正在使用的对象的变量,以防出现并发问题,尽管我可能是偏执狂。在实践中,我意识到我想做的事情非常清楚:我只是想暂停无限循环线程,将变量更改为我想要的,然后重新启动。我通过以下方式做到了这一点:
public void run() {
init();
while (shouldIRun) {
if (shouldIWait) {
iAmWaiting=true;
while (shouldIWait) { };
iAmWaiting=false;
}
updateGameState();
checkUserInput();
updateGameScreen(getGraphics());
this.flushGraphics();
}
}
我在想的是以下内容。如果我现在想从“基本”线程“暂停”第二个线程,我只需将
shouldIWait
变量设置为 true,然后循环直到我注意到 iAmWaiting
变量也是 true。我现在肯定知道第二个线程已经暂停,我确切地知道它在哪里暂停,“暂停”实际上是指“暂时陷入无限循环”。我现在可以使用一些基本变量,重新启动关卡,并大致解决问题,然后最后将 shouldIWait
设置回 false 并重新开始。我的问题是:这对我来说很好用,但有点混杂。是否有一些完全标准的方式来做可能是常见的事情——在给定的点暂停一个线程,然后在我准备好时重新启动它,这比我正在做的更好吗?特别是我怀疑“将 java 放入无限循环”可能不是一件聪明的事情。
最佳答案
通常,这就是您使用 Object.wait()
和 Object.notify()
的目的。
有几种方法可以根据您的情况实现它,但这里有一个简单的例子:
Object monitor = new Object();
volatile boolean done = false, wait = false;
/* Running on one thread: */
public void run() {
synchronized(monitor) {
while(!done) {
while(wait) {
monitor.wait();
}
gameLogicAndStuff();
}
}
}
/* Running on another thread: */
public void showResetForm() {
wait = true;
synchronized(monitor) {
actuallyShowResetForm();
wait = false;
monitor.notifyAll();
}
}