优雅地中断java线程
我写了一个Java ME益智游戏。我已经编写了这样的代码:有一个线程在应用程序启动时启动,并且一旦游戏启动,就会有第二个线程在无限循环中运行 - 主循环。第二个线程看起来像这样,在一个点上:优雅地中断java线程
public void run() {
init();
while (shouldIRun) {
updateGameState();
checkUserInput();
updateGameScreen(getGraphics());
this.flushGraphics();
}
}
可爱。这个线程只是运行并运行,直到我想杀死它,当我将布尔型shouldIRun
设置为false时,它会优雅地退出。
但后来我意识到,我想要更多。游戏是一款益智游戏,玩家可能会做出错误的动作,然后卡住。发生这种情况时,他们可以启动表单并选择“重启级别”选项。一个标志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
变量也是如此。我现在知道第二个线程已经暂停,并且我确切地知道它在哪里暂停,“暂停”的位置我实际上是指“暂时停留在无限循环中”。我现在可以用一些重要的变量来重复一遍,重新启动关卡,并且通常会将其排除,然后最终将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();
}
}
我会接受这个,因为它教会了我一些东西。不管我是否会执行它,都是另一回事:-)但是我可能会在一天结束时。 – 2012-02-04 12:36:10
也许这将只是简单的杀死线程并启动一个新的与新的水平。
如果有需要从一个级别进行到下的一些信息,也许你可以重构你的代码,你先收集一些一般信息,然后开始为每个级别一个线程。 (和通过启动一个线程,我的意思是使用一个线程池。)
我不认为你正在与忙等待做什么是邪恶的。正如Ben Flynn在评论中提到的那样,您可以通过循环Thread.sleep(50)来使其等待半忙。
该程序的以前版本用于执行此操作,但需要传递各种参数,我对某些看起来可能会发生的参考循环有点担心 - 然后我意识到我可以按照上面的建议进行操作取而代之。 – 2012-02-04 12:35:21
你可以至少引入一个简短的线程睡觉while(shouldIWait) – 2012-02-03 23:25:47
我看到 - 强制第二个线程睡觉,从而促使主线程回到行动? OK - 完成:-)但它仍然是一个混乱?我期待有人说“哦,只是使用t.pauseAtThisPointUntilISaySo()”或其他... – 2012-02-03 23:31:23
是的,这就是为什么我没有提供它作为答案。 =)我猜想有人会和我一起讨论线程等待,但我认为我所建议的是某种自旋,有办法使用yielding和interrupts,这也可能是有效的。 – 2012-02-03 23:40:34