Reputation: 537
I have written a Java ME puzzle game. I have written the code thus: there is a thread that starts when the app starts, and, once the game has got going, there's a second thread that just runs in an infinite loop -- the main game loop. The second thread looked like this, at one point:
public void run() {
init();
while (shouldIRun) {
updateGameState();
checkUserInput();
updateGameScreen(getGraphics());
this.flushGraphics();
}
}
Lovely. This thread just runs and runs, until I want to kill it, when I just set the boolean shouldIRun
to false, whereupon it exits gracefully.
But later on I realised I wanted more. The game is a puzzle game and it's possible for the player to make the wrong moves and then get stuck. When this happens they can fire up a form and select the "restart level" option. A flag restartLevel
then gets set, and when the infinite loop gets to the updateGameState()
method the level is restarted. But this feels to me like a bit of a gamble -- I don't want to start changing variables of objects being used in the main loop in case of concurrency issues, although I'm probably being paranoid. In practice what I realised I wanted to do was very clear: I simply wanted to pause the infinite loop thread, change the variables to what I wanted, and then restart.
I have done this in the following way:
public void run() {
init();
while (shouldIRun) {
if (shouldIWait) {
iAmWaiting=true;
while (shouldIWait) { };
iAmWaiting=false;
}
updateGameState();
checkUserInput();
updateGameScreen(getGraphics());
this.flushGraphics();
}
}
What I am thinking is the following. If I now want to "pause" this second thread, from the "base" thread, I just set the shouldIWait
variable to true, and then just loop until I notice the iAmWaiting
variable is also true. I now know for sure that the second thread has paused and I know precisely where it has paused, where by "paused" I actually mean "is stuck in an infinite loop for the time being". I can now goof around with some essential variables, restart the level, and generally sort things out, and then finally set shouldIWait
back to false and off we go again.
My question is this: this works fine, for me, but smacks of being a kludge. Is there some completely standard way of doing what is presumably a common thing -- pausing a thread at a given point and then restarting it when I'm ready, which is better than what I'm doing? In particular I suspect that "putting java into an infinite loop" is perhaps not a clever thing to do.
Upvotes: 4
Views: 337
Reputation: 5326
Maybe it would just be simpler to kill the thread and start a new one with the new level.
If there is some information that needs to be carried from one level to the next, maybe you could refactor your code such that you gather some general information first and then start a thread for each level. (And by starting a thread, I mean using a thread pool.)
I don't think what you are currently doing with busy waiting is evil. As Ben Flynn mentioned in the comments, you could make it semi-busy waiting by looping over Thread.sleep(50).
Upvotes: 1
Reputation: 25855
Normally, this is what you would use Object.wait()
and Object.notify()
for.
There are a couple of ways to implement it for your situation, but here's a simple example:
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();
}
}
Upvotes: 1