IllegalMonitorStateException?
Following program is based on Sun's Flipper2.java example
(http://java.sun.com/docs/books/tutorial/uiswing/examples/QandE/Flipper2Project/src/QandE/Flipper2.java).
Instead of slowing the background task, I want to suspend the background
task until I get a signal from the user interface to flip another coin.
In the background task I replaced sleep() with wait(). Added a JButton
(wakeupBotton) and extended the actionPerformed method to issue a
notifyAll() statement to wakeup the background task, when the
wakeupBotton is clicked.
Instead of waking up the wait(), notifyAll() causes an
IllegalMonitorStateException.
I looked up the API and found notifyAll() should only be called by a
thread that is the owner of this object's monitor. A thread becomes the
owner of the object's monitor in one of three ways:
* By executing a synchronized instance method of that object.
* By executing the body of a synchronized statement that synchronizes on
the object.
* For objects of type Class, by executing a synchronized static method
of that class.
Only one thread at a time can own an object's monitor.
Throws: IllegalMonitorStateException - if the current thread is not the
owner of this object's monitor.
In the context of my program, I don't understand how to do that. What
modifications do I need to make this work?
Here is the program:
package concurrency;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.border.Border;
public class Flipper extends JFrame implements
ActionListener {
private static final long serialVersionUID = 1L;
private final Border border = BorderFactory
.createLoweredBevelBorder();
private final GridBagConstraints constraints;
private FlipTask flipTask;
private final JTextField headsText, totalText, devText;
private final JButton startButton, stopButton,
wakeupButton;
public void actionPerformed(final ActionEvent e) {
final String eventActionCommand = ((JButton) e
.getSource()).getActionCommand();
if (startButton.getActionCommand().equals(
eventActionCommand))
/* Handle Start Button */
{
startButton.setEnabled(false);
stopButton.setEnabled(true);
wakeupButton.setEnabled(true);
(flipTask = new FlipTask()).execute();
} else if (stopButton.getActionCommand().equals(
eventActionCommand))
/* Handle Stop Button */
{
startButton.setEnabled(true);
stopButton.setEnabled(false);
wakeupButton.setEnabled(false);
flipTask.cancel(true);
flipTask = null;
} else
/* Handle Wake Up Button (signal flipTask to wakeup) */
notifyAll();
}
private class FlipTask extends
SwingWorker<Void, FlipPair> {
@Override
protected Void doInBackground() {
long heads = 0;
long total = 0;
final Random random = new Random();
while (!isCancelled()) {
total++;
if (random.nextBoolean())
heads++;
publish(new FlipPair(heads, total));
/* Wait for signal from wakeupButton to continue */
try {
wait();
} catch (final InterruptedException e) {
/* Ignore */
}
}
return null;
}
@Override
protected void process(final List<FlipPair> pairs) {
final FlipPair pair = pairs.get(pairs.size() - 1);
headsText.setText(String.format("%d", pair.heads));
totalText.setText(String.format("%d", pair.total));
devText.setText(String.format("%.10g",
(double) pair.heads / (double) pair.total
- 0.5));
}
}
private static class FlipPair {
private final long heads, total;
FlipPair(final long heads, final long total) {
this.heads = heads;
this.total = total;
}
}
public Flipper() {
super("Flipper");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Make text boxes
getContentPane().setLayout(new GridBagLayout());
constraints = new GridBagConstraints();
constraints.insets = new Insets(3, 10, 3, 10);
headsText = makeText();
totalText = makeText();
devText = makeText();
// Make buttons
startButton = makeButton("Start");
wakeupButton = makeButton("Wake Up");
wakeupButton.setEnabled(false);
stopButton = makeButton("Stop");
stopButton.setEnabled(false);
// Display the window.
pack();
setVisible(true);
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Flipper();
}
});
}
private JButton makeButton(final String caption) {
final JButton b = new JButton(caption);
b.setActionCommand(caption);
b.addActionListener(this);
getContentPane().add(b, constraints);
return b;
}
private JTextField makeText() {
final JTextField t = new JTextField(10);
t.setEditable(false);
t.setHorizontalAlignment(JTextField.RIGHT);
t.setBorder(border);
getContentPane().add(t, constraints);
return t;
}
}
--
Dan Maloney