Java Reference
In-Depth Information
The methods of
Observable
use synchronization to ensure consistency
when concurrent access to the object occurs. For example, one thread
can be trying to add an observer while another is trying to remove one
and a third is effecting a change on the
Observable
object. While syn-
chronization is necessary for maintaining the observer list and making
changes to the "changed" flag, no synchronization lock should be held
when the
update
method of the observers is invoked. Otherwise it would
be very easy to create deadlocks. The default implementation of
noti-
fyObservers
takes a synchronized snapshot of the current observer list
before invoking
update
. This means that an observer that is removed
while
notifyObservers
is still in progress will still be notified of the last
change. Conversely, an observer that is added while
notifyObservers
is
still in progress will not be notified of the current change. If the
Observ-
able
object allows concurrent invocations of methods that generate no-
tifications, it is possible for
update
to be called concurrently on each
Ob-
server
object. Consequently,
Observer
objects must use appropriate syn-
chronization 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 no-
tified 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
Ob-
servable
:
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);