UUIDTimer produces the time stamps required for time-based UUIDs. It works as
outlined in the UUID specification, with following implementation:
- Java classes can only product time stamps with maximum resolution of one
millisecond (at least before JDK 1.5). To compensate, an additional counter
is used, so that more than one UUID can be generated between java clock
updates. Counter may be used to generate up to 10000 UUIDs for each distrinct
java clock value.
- Due to even lower clock resolution on some platforms (older Windows
versions use 55 msec resolution), timestamp value can also advanced ahead of
physical value within limits (by default, up 100 millisecond ahead of
reported), iff necessary (ie. 10000 instances created before clock time
advances).
- As an additional precaution, counter is initialized not to 0 but to a
random 8-bit number, and each time clock changes, lowest 8-bits of counter
are preserved. The purpose it to make likelihood of multi-JVM multi-instance
generators to collide, without significantly reducing max. UUID generation
speed. Note though that using more than one generator (from separate JVMs) is
strongly discouraged, so hopefully this enhancement isn't needed. This 8-bit
offset has to be reduced from total max. UUID count to preserve ordering
property of UUIDs (ie. one can see which UUID was generated first for given
UUID generator); the resulting 9500 UUIDs isn't much different from the
optimal choice.
- Finally, as of version 2.0 and onwards, optional external timestamp
synchronization can be done. This is done similar to the way UUID
specification suggests; except that since there is no way to lock the whole
system, file-based locking is used. This works between multiple JVMs and Jug
instances.
Some additional assumptions about calculating the timestamp:
- System.currentTimeMillis() is assumed to give time offset in UTC, or at
least close enough thing to get correct timestamps. The alternate route would
have to go through calendar object, use TimeZone offset to get to UTC, and
then modify. Using currentTimeMillis should be much faster to allow rapid
UUID creation.
- Similarly, the constant used for time offset between 1.1.1970 and start
of Gregorian calendar is assumed to be correct (which seems to be the case
when testing with Java calendars).
Note about synchronization: this class is assumed to always be called from a
synchronized context (caller locks on either this object, or a similar timer
lock), and so has no method synchronization.