I've got a runnable Game object. The game is played through twitter, so when the Game comes to a point where player input is needed I've got a function like so:
private synchronized void waitForInput() {
input = "";
while(input == ""){
System.out.println("Waiting...");
try{
synchronized(this){
// wait for a second then continue to check the loop condition
this.wait(1000);
}
}
catch(Exception e){
System.out.println("failed to wait.");
e.printStackTrace();
}
}
System.out.println("Finished waiting.");
}
The private volatile String input
is an instance variable of the Player class. I have a Twitter Listener waiting for someone to tweet the bot, then upon receiving said tweet it takes the tweet text as input and sets this instance variable, breaking out of the loop. I'm not particularly happy with this approach, as wait is kind of pointless here - and there's no need for use of notify() here - it seems like I'm approaching this wrong. However, I have no idea how I could wait() and then also access the instance variable input to update it since the thread is in the synchronized block and can't execute the setter method for input.
Anyone have any ideas for a better approach?
When calling wait()
you need a synchronized
block, but it releases the lock as soon as it is waiting. It will automatically regain the lock when it wakes up. So your code should look like this.. No need to use any timeouts..
private void waitForInput() {
String input = "";
// Though we are not waiting infinitely without timeout, we still need
// while loop.
// Since JVM in some cases might wake-up thread without notify calls,
// this is called "spurious" wake-ups.
synchronized (this) {
while (input.equals("")) {
System.out.println("Waiting...");
try {
this.wait();//Wait infinitely, or till notify called.
//Lock is released but current thread is blocked, so call on some Async thread if required.
} catch (Exception e) {
System.out.println("failed to wait.");
e.printStackTrace();
}
}
}
System.out.println("Finished waiting.");
}
//Your twitter bot should call this method, when new input received.
public void wakeup(String input) {
synchronized (this) {
this.input = input;
notifyAll();
}
}