First, a little more on wait sets, notification, monitors, etc. (If you already know this stuff, bear with me.) In
Java, any object can act as a
monitor - that's an entity with a single
lock and a
wait set.
When an object's <code>wait</code> method is executed, the currently executing thread enters that object's wait set. As long as it's there, it sits idle.
When an object's <code>notify</code> or <code>notifyAll</code> method is called, one or all of the threads in its wait set are removed from the set. They then actively contend for the object's lock, and the one that gets the lock goes on to execute.
In the situation here, we want only one of the threads to execute at one time. The easy way to do this is to arrange for one of them to be in an object's wait set and the other to be executing, and have them change places periodically. They change places when the executing thread calls the object's <code>notify</code> method (so the other one leaves the wait set) and then calls the object's <code>wait</code> method. When the executing thread enters the wait set, it gives up the lock (which is grabbed by the newly awakened thread, which can then execute) and takes the other one's place in the wait set. Voila! The threads have changed places.
There are lots of ways to arrange this behavior in code; here's one that makes what's going on explicit:
- The outer class no longer implements <code>Runnable</code>. It's the controller, not a thread.
- Add a field of type <code>Object</code> to the outer class, call it <code>monitor</code>. Initialize it with <code>new Object()</code>.
- Rename the inner class <code>ClassA</code> and don't synchronize its entire <code>run</code> method. Instead, place the body of its <code>run</code> in a block marked <code>synchronized (monitor) {...}</code>.
- Create another inner class that also implements <code>Runnable</code>, called <code>ClassB</code>. Move the old <code>run</code> method from the outer class inside <code>ClassB</code>. Enclose its body in <code>synchronized (monitor) {...}</code> just like the other. Now the two are set to sync on the same object.
- Make sure each <code>run</code> method has a loop that prints its line, calls <code>monitor.notify</code>, then <code>monitor.wait</code>.
- In <code>main</code>, create threads from the inner classes and start them.
You might have to mess with things a little to get it all to work, but that's a fairly general solution for ensuring only one thread can run at once. In a larger program, you might use this arrangement to protect <code>monitor</code> from being accessed by both threads at the same time.
jply