Java Reference
In-Depth Information
158 }
159 }
160
161 log.exiting("DvdFileAccess", "getDvdList");
162 return returnValue;
163 }
As with the file itself, the map of UPC numbers to file locations is a single object used by
many threads. However, in most cases, the threads will only be reading from the recordNumbers
map—it will be much rarer for a method to update this map. Prior to JDK 5, we would have
synchronized all access to the recordNumbers map, which would have meant that only one
thread could ever access it at any given time. With JDK 5 we now have ReadWriteLock s that
allow for greater concurrency. Instead of synchronizing code, we encapsulate the code inside
calls to lock and unlock methods. Multiple threads can own a read lock on a single object at
any given time, but only one thread can own a write lock at any given time.
If we are running this from the constructor, then we will be updating the recordNumbers
map, so we will not want any other thread to be accessing the map in the meantime—a write
lock will ensure this for us. This is set in line 136, and released in the finally block at line 157.
It is important to ensure that the lock is released even if an exception is thrown; hence the call
to unlock is in the finally block to ensure it is always run. This is recommended whenever you
are using the new locking classes.
Line 150 adds our UPC string and the location in the file into the map. Using generics and
autoboxing (introduced in Chapter 2) allows us to keep this code simple, while simultaneously
ensuring that invalid data is not entered into our recordNumbers map. At the very start of the
class we declared that the recordNumbers could only contain a String as the key and a Long as
the value with the following code:
51 private static Map<String, Long> recordNumbers
52 = new HashMap<String, Long>();
The compiler will then use this to validate at compile time that we are storing String s as
the key and a Long as the value within this Map . Using autoboxing allows us to add a String and
a primitive long to the Map , knowing that Java will automatically convert the primitive long to
the wrapper Long class required for the Map .
Prior to JDK 5, there was no way for the compiler to validate that the type of data we were
adding to a collection was the type of data we actually wanted to allow into the collection. You
will now get an error message if you attempt to add the wrong type of data to our collection.
If you would like to see an example of how this works, try changing line 150 as follows:
recordNumbers.put(dvd.getUPC(), (int) locationInFile);
The JDK 5 Java compiler will now produce an error message, because the type of data we
are potentially adding to the Map no longer matches our declared allowable contents:
sampleproject\db\DvdFileAccess.java:150: put(java.lang.String,java.lang.Long)
in java.util.Map<java.lang.String,java.lang.Long> cannot be applied to
(java.lang.String,int)
recordNumbers.put(dvd.getUPC(), (int) locationInFile);
^
1 error
Search WWH ::




Custom Search