is added while notifyObservers is still in progress will not be notified of the current change. If the
Observable object allows concurrent invocations of methods that generate notifications, it is possible for
update to be called concurrently on each Observer object. Consequently, Observer objects must use
appropriate synchronization within update to ensure proper operation.
The default implementation of notifyObservers uses the invoking thread to invoke update on each
observer. The order in which observers are notified is not specified. A subclass could specialize
notifyObservers to use a different threading model, and/or to provide ordering guarantees.
The following example illustrates how Observer/Observable might be used to monitor users of a
system. First, we define a Users class that is Observable:
import java.util.*;
public class Users extends Observable {
private Map<String, UserState> loggedIn =
new HashMap<String, UserState>();
public void login(String name, String password)
throws BadUserException
{
if (!passwordValid(name, password))
throw new BadUserException(name);
UserState state = new UserState(name);
loggedIn.put(name, state);
setChanged();
notifyObservers(state);
}
public void logout(UserState state) {
loggedIn.remove(state.name());
setChanged();
notifyObservers(state);
}
// ...
}
A Users object stores a map of users who are logged in and maintains UserState objects for each login.
When someone logs in or out, all Observer objects will be passed that user's UserState object. The
notifyObservers method sends messages only if the state changes, so you must invoke setChanged
on Users; otherwise, notifyObservers would do nothing.
Here is how an Observer that maintains a constant display of logged-in users might implement update to
watch a Users object:
import java.util.*;
public class Eye implements Observer {
Users watching;
public Eye(Users users) {
watching = users;
watching.addObserver(this);
}
public void update(Observable users, Object whichState)
{
if (users != watching)