/**
* This class manages a queue of ChangeObserver objects. Each time
* a change occurs to a Persistent object, the Persistent calls
* update() in all observers. Because RMI blocks during remote method
* calls, you need to do any display changes in a new thread. So
* update() calls ChangeMonitor.postChange() which adds the object
* to the stack. A separate thread then periodically checks the stack
* and calls observeChange() in each of the ChangeObserver instances
* on the stack.
*/
package imaginary.gui;
import java.util.Enumeration;
import java.util.Vector;
public class ChangeMonitor extends Thread {
// the monitor is a single thread that monitors the change queue
static private ChangeMonitor monitor = new ChangeMonitor();
/**
* Adds a ChangeObserver object onto the queue.
* @param observer the observer to add to the stack
*/
static public void postChange(ChangeObserver observer) {
ChangeMonitor.monitor.post(observer);
}
// The queue of ChangeObserver instances
private Vector queue = new Vector();
/**
* Constructs a new monitor thread that maintains the queue.
*/
public ChangeMonitor() {
super();
setDaemon(true);
start();
}
// Actually sticks the observer into the queue.
private void post(ChangeObserver observer) {
synchronized(queue) {
queue.addElement(observer);
}
}
/**
* Grabs the entire queue in an enumeration and calls observeChange()
* in each one.
* @see imaginary.gui.ChangeObserver#observeChange
*/
public void run() {
while( true ) {
Enumeration elems;
// Grab a queue enumeration quickly and release
// the synchronization.
synchronized(queue) {
if( !queue.isEmpty() ) {
elems = queue.elements();
queue = new Vector();
}
else {
elems = null;
}
}
if( elems != null ) {
while( elems.hasMoreElements() ) {
ChangeObserver o = (ChangeObserver)elems.nextElement();
o.observeChange();
}
}
try { Thread.sleep(500); }
catch( InterruptedException e ) { }
}
}
}
|