问题
I have a simple, variably sized tic-tac-toe App that works differently on different machines. On my laptop it works like I want it to and on my desktop, it gets stuck in the ButtonListener
class that implements ActionListener
. I'm pretty sure this is because of the way I am waiting for a action to be performed, using a while
loop. Here is the offending code snippet.
public void playOneTurn(int player) {
waiting = true;
while (waiting) {
// Do nothing, touchEvent will change waiting.
}
}
I meant for this method to simply wait for a valid spot to be selected and for waiting
to be flipped in the ButtonListener
:
class ButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("TOUCHEVENT");
for (i = 0; i < size; i++)
for (j = 0; j < size; j++)
if (e.getSource() == cells[i][j]) {
if (model[i][j] == 'e') {
cells[i][j].setText("");
currentSpot[0] = i;
currentSpot[1] = j;
if (count % 2 == 0) {
cells[i][j].setBackground(Color.GREEN);
cells[i][j].setIcon(X_MARK);
model[i][j] = 'x';
count++;
waiting = false;
} else {
cells[i][j].setBackground(Color.CYAN);
cells[i][j].setIcon(O_MARK);
model[i][j] = 'o';
count++;
waiting = false;
}
} else {
System.out.println("Hey, you can't move there silly!");
}
}
}
}
I know nothing about threads but I believe that the ButtonListener
is starting a thread, and because of the way I'm waiting on it, with the while
loop, the thread is never stopped to let the rest of my code run on certain machines.
Is my error in using the while loop to wait on an Event to flip a boolean, and if so, how would I properly wait for it?
回答1:
Do not simply use while(true)
loop. It will take up your CPU usage. Use synchronization
instead. Create a private final Object
and call wait()
on it. Prior to this send a reference of this object to the MessageListener. When your operation in MessageListener is completed you can call notify()
on it.
Also take care of Spurious wakeups.
回答2:
You should redesign your application. There is no need to wait at all. The entire state of your application will not change unless there is some event (i.e. user input) which triggers such a change. That’s especially true for a tic-tac-toe game. The condition you want to wait for cannot become true unless some user input changed the state in way that allows it. Therefore you can check for the condition inside the listener at places where the condition could have become true. And then react on it immediately.
Therefore you should implement listeners which react on events, change the state of your application and return. The next state transition will happen when the next event occurs, not a single CPU cycle before that. If you want to do changes independent of user generated events, i.e. animations, use a Timer
which will generate appropriate events.
来源:https://stackoverflow.com/questions/21874923/how-to-properly-wait-until-actionlistener-is-executed