Java Reference
In-Depth Information
ditional constraints on the valid values for vehicle locations. If it needed to be able to “veto”
changes to vehicle locations or to take action when a location changes, the approach taken by
PublishingVehicleTracker would not be appropriate.
4.4. Adding Functionality to Existing Thread-safe Classes
The Java class library contains many useful “building block” classes. Reusing existing
classes is often preferable to creating new ones: reuse can reduce development effort, de-
velopment risk (because the existing components are already tested), and maintenance cost.
Sometimes a thread-safe class that supports all of the operations we want already exists, but
often the best we can find is a class that supports almost all the operations we want, and then
we need to add a new operation to it without undermining its thread safety.
As an example, let's say we need a thread-safe List with an atomic put-ifabsent operation.
The synchronized List implementations nearly do the job, since they provide the con-
tains and add methods from which we can construct a put-if-absent operation.
The concept of put-if-absent is straightforward enough—check to see if an element is in the
collection before adding it, and do not add it if it is already there. (Your “check-then-act”
warning bells should be going off now.) The requirement that the class be thread-safe impli-
citly adds another requirement—that operations like put-if-absent be atomic . Any reasonable
interpretation suggests that, if you take a List that does not contain object X , and add X
twice with put-if-absent, the resulting collection contains only one copy of X . But, if put-if-
absent were not atomic, with some unlucky timing two threads could both see that X was not
present and both add X , resulting in two copies of X .
The safest way to add a new atomic operation is to modify the original class to support the
desired operation, but this is not always possible because you may not have access to the
source code or may not be free to modify it. If you can modify the original class, you need to
understand the implementation's synchronization policy so that you can enhance it in a man-
ner consistent with its original design. Adding the new method directly to the class means
that all the code that implements the synchronization policy for that class is still contained in
one source file, facilitating easier comprehension and maintenance.
Another approach is to extend the class, assuming it was designed for extension. Bet-
terVector in Listing 4.13 extends Vector to add a putIfAbsent method. Extending
Vector is straightforward enough, but not all classes expose enough of their state to sub-
classes to admit this approach.
Search WWH ::




Custom Search